Auto merge of #113146 - matthiaskrgr:rollup-bxtr51e, r=matthiaskrgr

Rollup of 7 pull requests

Successful merges:

 - #112670 (privacy: Type privacy lints fixes and cleanups)
 - #112929 (Test that we require implementing trait items whose bounds don't hold in the current impl)
 - #113054 (Make `rustc_on_unimplemented` std-agnostic)
 - #113137 (don't suggest `move` for borrows that aren't closures)
 - #113139 (style-guide: Clarify let-else further)
 - #113140 (style-guide: Add an example of formatting a multi-line attribute)
 - #113143 (style-guide: Narrow guidance about references and dereferencing)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2023-06-29 04:34:46 +00:00
commit 0a32ca9831
47 changed files with 569 additions and 204 deletions

View file

@ -1730,18 +1730,19 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
(
Some(name),
BorrowExplanation::UsedLater(LaterUseKind::ClosureCapture, var_or_use_span, _),
) => self.report_escaping_closure_capture(
borrow_spans,
borrow_span,
&RegionName {
name: self.synthesize_region_name(),
source: RegionNameSource::Static,
},
ConstraintCategory::CallArgument(None),
var_or_use_span,
&format!("`{}`", name),
"block",
),
) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
.report_escaping_closure_capture(
borrow_spans,
borrow_span,
&RegionName {
name: self.synthesize_region_name(),
source: RegionNameSource::Static,
},
ConstraintCategory::CallArgument(None),
var_or_use_span,
&format!("`{}`", name),
"block",
),
(
Some(name),
BorrowExplanation::MustBeValidFor {
@ -1754,7 +1755,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
span,
..
},
) if borrow_spans.for_generator() | borrow_spans.for_closure() => self
) if borrow_spans.for_generator() || borrow_spans.for_closure() => self
.report_escaping_closure_capture(
borrow_spans,
borrow_span,

View file

@ -543,6 +543,8 @@ declare_features! (
/// Allows creation of instances of a struct by moving fields that have
/// not changed from prior instances of the same struct (RFC #2528)
(active, type_changing_struct_update, "1.58.0", Some(86555), None),
/// Allows using type privacy lints (`private_interfaces`, `private_bounds`, `unnameable_types`).
(active, type_privacy_lints, "CURRENT_RUSTC_VERSION", Some(48054), None),
/// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
(active, unix_sigpipe, "1.65.0", Some(97889), None),
/// Allows unsized fn parameters.

View file

@ -665,9 +665,7 @@ declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS])
impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
&& cx.tcx.local_visibility(item.owner_id.def_id).is_public())
{
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
return;
}
let (def, ty) = match item.kind {
@ -786,9 +784,7 @@ impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) {
if !(cx.effective_visibilities.is_reachable(item.owner_id.def_id)
&& cx.tcx.local_visibility(item.owner_id.def_id).is_public())
{
if !cx.effective_visibilities.is_reachable(item.owner_id.def_id) {
return;
}

View file

@ -4264,6 +4264,7 @@ declare_lint! {
/// ### Example
///
/// ```rust,compile_fail
/// # #![feature(type_privacy_lints)]
/// # #![allow(unused)]
/// # #![allow(private_in_public)]
/// #![deny(private_interfaces)]
@ -4288,6 +4289,7 @@ declare_lint! {
pub PRIVATE_INTERFACES,
Allow,
"private type in primary interface of an item",
@feature_gate = sym::type_privacy_lints;
}
declare_lint! {
@ -4298,6 +4300,7 @@ declare_lint! {
/// ### Example
///
/// ```rust,compile_fail
/// # #![feature(type_privacy_lints)]
/// # #![allow(private_in_public)]
/// # #![allow(unused)]
/// #![deny(private_bounds)]
@ -4317,7 +4320,8 @@ declare_lint! {
/// the item actually provides.
pub PRIVATE_BOUNDS,
Allow,
"private type in secondary interface of an item"
"private type in secondary interface of an item",
@feature_gate = sym::type_privacy_lints;
}
declare_lint! {
@ -4327,6 +4331,7 @@ declare_lint! {
/// ### Example
///
/// ```rust,compile_fail
/// # #![feature(type_privacy_lints)]
/// # #![allow(unused)]
/// #![deny(unnameable_types)]
/// mod m {
@ -4345,5 +4350,6 @@ declare_lint! {
/// you can name the type `T` as well, this lint attempts to enforce this rule.
pub UNNAMEABLE_TYPES,
Allow,
"effective visibility of a type is larger than the area in which it can be named"
"effective visibility of a type is larger than the area in which it can be named",
@feature_gate = sym::type_privacy_lints;
}

View file

@ -4,6 +4,7 @@
use crate::ty::{TyCtxt, Visibility};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def::DefKind;
use rustc_macros::HashStable;
use rustc_query_system::ich::StableHashingContext;
use rustc_span::def_id::{LocalDefId, CRATE_DEF_ID};
@ -148,13 +149,12 @@ impl EffectiveVisibilities {
};
}
pub fn check_invariants(&self, tcx: TyCtxt<'_>, early: bool) {
pub fn check_invariants(&self, tcx: TyCtxt<'_>) {
if !cfg!(debug_assertions) {
return;
}
for (&def_id, ev) in &self.map {
// More direct visibility levels can never go farther than less direct ones,
// neither of effective visibilities can go farther than nominal visibility,
// and all effective visibilities are larger or equal than private visibility.
let private_vis = Visibility::Restricted(tcx.parent_module_from_def_id(def_id));
let span = tcx.def_span(def_id.to_def_id());
@ -175,17 +175,20 @@ impl EffectiveVisibilities {
ev.reachable_through_impl_trait
);
}
let nominal_vis = tcx.visibility(def_id);
// FIXME: `rustc_privacy` is not yet updated for the new logic and can set
// effective visibilities that are larger than the nominal one.
if !nominal_vis.is_at_least(ev.reachable_through_impl_trait, tcx) && early {
span_bug!(
span,
"{:?}: reachable_through_impl_trait {:?} > nominal {:?}",
def_id,
ev.reachable_through_impl_trait,
nominal_vis
);
// All effective visibilities except `reachable_through_impl_trait` are limited to
// nominal visibility. For some items nominal visibility doesn't make sense so we
// don't check this condition for them.
if !matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) {
let nominal_vis = tcx.visibility(def_id);
if !nominal_vis.is_at_least(ev.reachable, tcx) {
span_bug!(
span,
"{:?}: reachable {:?} > nominal {:?}",
def_id,
ev.reachable,
nominal_vis
);
}
}
}
}
@ -212,7 +215,7 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
pub fn update(
&mut self,
id: Id,
nominal_vis: Option<Visibility>,
max_vis: Option<Visibility>,
lazy_private_vis: impl FnOnce() -> Visibility,
inherited_effective_vis: EffectiveVisibility,
level: Level,
@ -236,8 +239,8 @@ impl<Id: Eq + Hash> EffectiveVisibilities<Id> {
if !(inherited_effective_vis_at_prev_level == inherited_effective_vis_at_level
&& level != l)
{
calculated_effective_vis = if let Some(nominal_vis) = nominal_vis && !nominal_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
nominal_vis
calculated_effective_vis = if let Some(max_vis) = max_vis && !max_vis.is_at_least(inherited_effective_vis_at_level, tcx) {
max_vis
} else {
inherited_effective_vis_at_level
}

View file

@ -73,14 +73,10 @@ impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> {
/// in `impl Trait`, see individual comments in `DefIdVisitorSkeleton::visit_ty`.
trait DefIdVisitor<'tcx> {
type BreakTy = ();
const SHALLOW: bool = false;
const SKIP_ASSOC_TYS: bool = false;
fn tcx(&self) -> TyCtxt<'tcx>;
fn shallow(&self) -> bool {
false
}
fn skip_assoc_tys(&self) -> bool {
false
}
fn visit_def_id(
&mut self,
def_id: DefId,
@ -135,11 +131,7 @@ where
fn visit_trait(&mut self, trait_ref: TraitRef<'tcx>) -> ControlFlow<V::BreakTy> {
let TraitRef { def_id, substs, .. } = trait_ref;
self.def_id_visitor.visit_def_id(def_id, "trait", &trait_ref.print_only_trait_path())?;
if self.def_id_visitor.shallow() {
ControlFlow::Continue(())
} else {
substs.visit_with(self)
}
if V::SHALLOW { ControlFlow::Continue(()) } else { substs.visit_with(self) }
}
fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
@ -158,7 +150,7 @@ where
)
};
self.visit_trait(trait_ref)?;
if self.def_id_visitor.shallow() {
if V::SHALLOW {
ControlFlow::Continue(())
} else {
assoc_substs.iter().try_for_each(|subst| subst.visit_with(self))
@ -208,7 +200,7 @@ where
| ty::Closure(def_id, ..)
| ty::Generator(def_id, ..) => {
self.def_id_visitor.visit_def_id(def_id, "type", &ty)?;
if self.def_id_visitor.shallow() {
if V::SHALLOW {
return ControlFlow::Continue(());
}
// Default type visitor doesn't visit signatures of fn types.
@ -232,7 +224,7 @@ where
self.def_id_visitor.visit_def_id(alias.def_id, "type alias", &ty);
}
ty::Alias(ty::Projection, proj) => {
if self.def_id_visitor.skip_assoc_tys() {
if V::SKIP_ASSOC_TYS {
// Visitors searching for minimal visibility/reachability want to
// conservatively approximate associated types like `<Type as Trait>::Alias`
// as visible/reachable even if both `Type` and `Trait` are private.
@ -244,7 +236,7 @@ where
return self.visit_projection_ty(proj);
}
ty::Alias(ty::Inherent, data) => {
if self.def_id_visitor.skip_assoc_tys() {
if V::SKIP_ASSOC_TYS {
// Visitors searching for minimal visibility/reachability want to
// conservatively approximate associated types like `Type::Alias`
// as visible/reachable even if `Type` is private.
@ -260,7 +252,7 @@ where
)?;
// This will also visit substs if necessary, so we don't need to recurse.
return if self.def_id_visitor.shallow() {
return if V::SHALLOW {
ControlFlow::Continue(())
} else {
data.substs.iter().try_for_each(|subst| subst.visit_with(self))
@ -319,11 +311,7 @@ where
}
}
if self.def_id_visitor.shallow() {
ControlFlow::Continue(())
} else {
ty.super_visit_with(self)
}
if V::SHALLOW { ControlFlow::Continue(()) } else { ty.super_visit_with(self) }
}
fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow<Self::BreakTy> {
@ -340,22 +328,20 @@ fn min(vis1: ty::Visibility, vis2: ty::Visibility, tcx: TyCtxt<'_>) -> ty::Visib
/// Visitor used to determine impl visibility and reachability.
////////////////////////////////////////////////////////////////////////////////
struct FindMin<'a, 'tcx, VL: VisibilityLike> {
struct FindMin<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> {
tcx: TyCtxt<'tcx>,
effective_visibilities: &'a EffectiveVisibilities,
min: VL,
}
impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL> {
impl<'a, 'tcx, VL: VisibilityLike, const SHALLOW: bool> DefIdVisitor<'tcx>
for FindMin<'a, 'tcx, VL, SHALLOW>
{
const SHALLOW: bool = SHALLOW;
const SKIP_ASSOC_TYS: bool = true;
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn shallow(&self) -> bool {
VL::SHALLOW
}
fn skip_assoc_tys(&self) -> bool {
true
}
fn visit_def_id(
&mut self,
def_id: DefId,
@ -371,17 +357,19 @@ impl<'a, 'tcx, VL: VisibilityLike> DefIdVisitor<'tcx> for FindMin<'a, 'tcx, VL>
trait VisibilityLike: Sized {
const MAX: Self;
const SHALLOW: bool = false;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self;
fn new_min<const SHALLOW: bool>(
find: &FindMin<'_, '_, Self, SHALLOW>,
def_id: LocalDefId,
) -> Self;
// Returns an over-approximation (`skip_assoc_tys` = true) of visibility due to
// Returns an over-approximation (`SKIP_ASSOC_TYS` = true) of visibility due to
// associated types for which we can't determine visibility precisely.
fn of_impl(
fn of_impl<const SHALLOW: bool>(
def_id: LocalDefId,
tcx: TyCtxt<'_>,
effective_visibilities: &EffectiveVisibilities,
) -> Self {
let mut find = FindMin { tcx, effective_visibilities, min: Self::MAX };
let mut find = FindMin::<_, SHALLOW> { tcx, effective_visibilities, min: Self::MAX };
find.visit(tcx.type_of(def_id).subst_identity());
if let Some(trait_ref) = tcx.impl_trait_ref(def_id) {
find.visit_trait(trait_ref.subst_identity());
@ -391,49 +379,28 @@ trait VisibilityLike: Sized {
}
impl VisibilityLike for ty::Visibility {
const MAX: Self = ty::Visibility::Public;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
fn new_min<const SHALLOW: bool>(
find: &FindMin<'_, '_, Self, SHALLOW>,
def_id: LocalDefId,
) -> Self {
min(find.tcx.local_visibility(def_id), find.min, find.tcx)
}
}
struct NonShallowEffectiveVis(EffectiveVisibility);
impl VisibilityLike for NonShallowEffectiveVis {
const MAX: Self = NonShallowEffectiveVis(EffectiveVisibility::from_vis(ty::Visibility::Public));
const SHALLOW: bool = false;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
let find = FindMin {
tcx: find.tcx,
effective_visibilities: find.effective_visibilities,
min: ShallowEffectiveVis(find.min.0),
};
NonShallowEffectiveVis(VisibilityLike::new_min(&find, def_id).0)
}
}
struct ShallowEffectiveVis(EffectiveVisibility);
impl VisibilityLike for ShallowEffectiveVis {
const MAX: Self = ShallowEffectiveVis(EffectiveVisibility::from_vis(ty::Visibility::Public));
// Type inference is very smart sometimes.
// It can make an impl reachable even some components of its type or trait are unreachable.
// E.g. methods of `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
// can be usable from other crates (#57264). So we skip substs when calculating reachability
// and consider an impl reachable if its "shallow" type and trait are reachable.
//
// The assumption we make here is that type-inference won't let you use an impl without knowing
// both "shallow" version of its self type and "shallow" version of its trait if it exists
// (which require reaching the `DefId`s in them).
const SHALLOW: bool = true;
fn new_min(find: &FindMin<'_, '_, Self>, def_id: LocalDefId) -> Self {
impl VisibilityLike for EffectiveVisibility {
const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public);
fn new_min<const SHALLOW: bool>(
find: &FindMin<'_, '_, Self, SHALLOW>,
def_id: LocalDefId,
) -> Self {
let effective_vis =
find.effective_visibilities.effective_vis(def_id).cloned().unwrap_or_else(|| {
find.effective_visibilities.effective_vis(def_id).copied().unwrap_or_else(|| {
let private_vis =
ty::Visibility::Restricted(find.tcx.parent_module_from_def_id(def_id));
EffectiveVisibility::from_vis(private_vis)
});
ShallowEffectiveVis(effective_vis.min(find.min.0, find.tcx))
effective_vis.min(find.min, find.tcx)
}
}
@ -492,14 +459,14 @@ impl<'tcx> EmbargoVisitor<'tcx> {
&mut self,
def_id: LocalDefId,
inherited_effective_vis: EffectiveVisibility,
nominal_vis: Option<ty::Visibility>,
max_vis: Option<ty::Visibility>,
level: Level,
) {
let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id));
if Some(private_vis) != nominal_vis {
if max_vis != Some(private_vis) {
self.changed |= self.effective_visibilities.update(
def_id,
nominal_vis,
max_vis,
|| private_vis,
inherited_effective_vis,
level,
@ -771,12 +738,21 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
}
}
hir::ItemKind::Impl(ref impl_) => {
let item_ev = ShallowEffectiveVis::of_impl(
// Type inference is very smart sometimes. It can make an impl reachable even some
// components of its type or trait are unreachable. E.g. methods of
// `impl ReachableTrait<UnreachableTy> for ReachableTy<UnreachableTy> { ... }`
// can be usable from other crates (#57264). So we skip substs when calculating
// reachability and consider an impl reachable if its "shallow" type and trait are
// reachable.
//
// The assumption we make here is that type-inference won't let you use an impl
// without knowing both "shallow" version of its self type and "shallow" version of
// its trait if it exists (which require reaching the `DefId`s in them).
let item_ev = EffectiveVisibility::of_impl::<true>(
item.owner_id.def_id,
self.tcx,
&self.effective_visibilities,
)
.0;
);
self.update_eff_vis(item.owner_id.def_id, item_ev, None, Level::Direct);
@ -784,9 +760,9 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> {
for impl_item_ref in impl_.items {
let def_id = impl_item_ref.id.owner_id.def_id;
let nominal_vis =
let max_vis =
impl_.of_trait.is_none().then(|| self.tcx.local_visibility(def_id));
self.update_eff_vis(def_id, item_ev, nominal_vis, Level::Direct);
self.update_eff_vis(def_id, item_ev, max_vis, Level::Direct);
if let Some(impl_item_ev) = self.get(def_id) {
self.reach(def_id, impl_item_ev).generics().predicates().ty();
@ -904,7 +880,12 @@ impl<'tcx> DefIdVisitor<'tcx> for ReachEverythingInTheInterfaceVisitor<'_, 'tcx>
_descr: &dyn fmt::Display,
) -> ControlFlow<Self::BreakTy> {
if let Some(def_id) = def_id.as_local() {
self.ev.update_eff_vis(def_id, self.effective_vis, None, self.level);
// All effective visibilities except `reachable_through_impl_trait` are limited to
// nominal visibility. If any type or trait is leaked farther than that, it will
// produce type privacy errors on any use, so we don't consider it leaked.
let max_vis = (self.level != Level::ReachableThroughImplTrait)
.then(|| self.ev.tcx.local_visibility(def_id));
self.ev.update_eff_vis(def_id, self.effective_vis, max_vis, self.level);
}
ControlFlow::Continue(())
}
@ -1876,10 +1857,9 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
return false;
};
// FIXME: `Level::Reachable` should be taken instead of `Level::Reexported`
let reexported_at_vis = *effective_vis.at_level(Level::Reexported);
let reachable_at_vis = *effective_vis.at_level(Level::Reachable);
if !vis.is_at_least(reexported_at_vis, self.tcx) {
if !vis.is_at_least(reachable_at_vis, self.tcx) {
let lint = if self.in_primary_interface {
lint::builtin::PRIVATE_INTERFACES
} else {
@ -1896,7 +1876,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
tcx: self.tcx,
})
.into(),
item_vis_descr: &vis_to_string(self.item_def_id, reexported_at_vis, self.tcx),
item_vis_descr: &vis_to_string(self.item_def_id, reachable_at_vis, self.tcx),
ty_span: vis_span,
ty_kind: kind,
ty_descr: descr.into(),
@ -2137,27 +2117,28 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
DefKind::Impl { .. } => {
let item = tcx.hir().item(id);
if let hir::ItemKind::Impl(ref impl_) = item.kind {
let impl_vis =
ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default());
let impl_vis = ty::Visibility::of_impl::<false>(
item.owner_id.def_id,
tcx,
&Default::default(),
);
// we are using the non-shallow version here, unlike when building the
// We are using the non-shallow version here, unlike when building the
// effective visisibilities table to avoid large number of false positives.
// For example:
// For example in
//
// impl From<Priv> for Pub {
// fn from(_: Priv) -> Pub {...}
// }
//
// lints shouldn't be emmited even `from` effective visibility
// is larger then `Priv` nominal visibility.
let impl_ev = Some(
NonShallowEffectiveVis::of_impl(
item.owner_id.def_id,
tcx,
self.effective_visibilities,
)
.0,
);
// lints shouldn't be emmited even if `from` effective visibility
// is larger than `Priv` nominal visibility and if `Priv` can leak
// in some scenarios due to type inference.
let impl_ev = Some(EffectiveVisibility::of_impl::<false>(
item.owner_id.def_id,
tcx,
self.effective_visibilities,
));
// check that private components do not appear in the generics or predicates of inherent impls
// this check is intentionally NOT performed for impls of traits, per #90586
@ -2284,7 +2265,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
changed: false,
};
visitor.effective_visibilities.check_invariants(tcx, true);
visitor.effective_visibilities.check_invariants(tcx);
if visitor.impl_trait_pass {
// Underlying types of `impl Trait`s are marked as reachable unconditionally,
// so this pass doesn't need to be a part of the fixed point iteration below.
@ -2301,7 +2282,7 @@ fn effective_visibilities(tcx: TyCtxt<'_>, (): ()) -> &EffectiveVisibilities {
break;
}
}
visitor.effective_visibilities.check_invariants(tcx, false);
visitor.effective_visibilities.check_invariants(tcx);
let mut check_visitor =
TestReachabilityVisitor { tcx, effective_visibilities: &visitor.effective_visibilities };

View file

@ -1558,6 +1558,7 @@ symbols! {
type_length_limit,
type_macros,
type_name,
type_privacy_lints,
u128,
u16,
u32,

View file

@ -532,7 +532,7 @@ pub trait Into<T>: Sized {
#[rustc_diagnostic_item = "From"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(on(
all(_Self = "&str", T = "std::string::String"),
all(_Self = "&str", any(T = "alloc::string::String", T = "std::string::String")),
note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
))]
pub trait From<T>: Sized {

View file

@ -310,7 +310,7 @@ where
/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
/// this type.
#[derive(Clone, Debug)]
#[unstable(feature = "trusted_len", issue = "37572")]
#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
struct FlattenCompat<I, U> {
iter: Fuse<I>,
frontiter: Option<U>,
@ -464,7 +464,7 @@ where
}
}
#[unstable(feature = "trusted_len", issue = "37572")]
#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
impl<I, U> Iterator for FlattenCompat<I, U>
where
I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@ -579,7 +579,7 @@ where
}
}
#[unstable(feature = "trusted_len", issue = "37572")]
#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
where
I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@ -649,7 +649,7 @@ where
}
}
#[unstable(feature = "trusted_len", issue = "37572")]
#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
unsafe impl<const N: usize, I, T> TrustedLen
for FlattenCompat<I, <[T; N] as IntoIterator>::IntoIter>
where
@ -657,7 +657,7 @@ where
{
}
#[unstable(feature = "trusted_len", issue = "37572")]
#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
unsafe impl<'a, const N: usize, I, T> TrustedLen
for FlattenCompat<I, <&'a [T; N] as IntoIterator>::IntoIter>
where
@ -665,7 +665,7 @@ where
{
}
#[unstable(feature = "trusted_len", issue = "37572")]
#[cfg_attr(bootstrap, unstable(feature = "trusted_len", issue = "37572"))]
unsafe impl<'a, const N: usize, I, T> TrustedLen
for FlattenCompat<I, <&'a mut [T; N] as IntoIterator>::IntoIter>
where

View file

@ -26,13 +26,13 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented(
on(
_Self = "std::ops::RangeTo<Idx>",
any(_Self = "core::ops::RangeTo<Idx>", _Self = "std::ops::RangeTo<Idx>"),
label = "if you meant to iterate until a value, add a starting value",
note = "`..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a \
bounded `Range`: `0..end`"
),
on(
_Self = "std::ops::RangeToInclusive<Idx>",
any(_Self = "core::ops::RangeToInclusive<Idx>", _Self = "std::ops::RangeToInclusive<Idx>"),
label = "if you meant to iterate until a value (including it), add a starting value",
note = "`..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant \
to have a bounded `RangeInclusive`: `0..=end`"
@ -43,7 +43,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
),
on(_Self = "&[]", label = "`{Self}` is not an iterator; try calling `.iter()`"),
on(
_Self = "std::vec::Vec<T, A>",
any(_Self = "alloc::vec::Vec<T, A>", _Self = "std::vec::Vec<T, A>"),
label = "`{Self}` is not an iterator; try calling `.into_iter()` or `.iter()`"
),
on(
@ -51,7 +51,7 @@ fn _assert_is_object_safe(_: &dyn Iterator<Item = ()>) {}
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(
_Self = "std::string::String",
any(_Self = "alloc::string::String", _Self = "std::string::String"),
label = "`{Self}` is not an iterator; try calling `.chars()` or `.bytes()`"
),
on(

View file

@ -575,59 +575,59 @@ impl<T: ?Sized> Copy for &T {}
#[lang = "sync"]
#[rustc_on_unimplemented(
on(
_Self = "std::cell::OnceCell<T>",
any(_Self = "core::cell:OnceCell<T>", _Self = "std::cell::OnceCell<T>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::OnceLock` instead"
),
on(
_Self = "std::cell::Cell<u8>",
any(_Self = "core::cell::Cell<u8>", _Self = "std::cell::Cell<u8>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU8` instead",
),
on(
_Self = "std::cell::Cell<u16>",
any(_Self = "core::cell::Cell<u16>", _Self = "std::cell::Cell<u16>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU16` instead",
),
on(
_Self = "std::cell::Cell<u32>",
any(_Self = "core::cell::Cell<u32>", _Self = "std::cell::Cell<u32>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU32` instead",
),
on(
_Self = "std::cell::Cell<u64>",
any(_Self = "core::cell::Cell<u64>", _Self = "std::cell::Cell<u64>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicU64` instead",
),
on(
_Self = "std::cell::Cell<usize>",
any(_Self = "core::cell::Cell<usize>", _Self = "std::cell::Cell<usize>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicUsize` instead",
),
on(
_Self = "std::cell::Cell<i8>",
any(_Self = "core::cell::Cell<i8>", _Self = "std::cell::Cell<i8>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI8` instead",
),
on(
_Self = "std::cell::Cell<i16>",
any(_Self = "core::cell::Cell<i16>", _Self = "std::cell::Cell<i16>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI16` instead",
),
on(
_Self = "std::cell::Cell<i32>",
any(_Self = "core::cell::Cell<i32>", _Self = "std::cell::Cell<i32>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI32` instead",
),
on(
_Self = "std::cell::Cell<i64>",
any(_Self = "core::cell::Cell<i64>", _Self = "std::cell::Cell<i64>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicI64` instead",
),
on(
_Self = "std::cell::Cell<isize>",
any(_Self = "core::cell::Cell<isize>", _Self = "std::cell::Cell<isize>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicIsize` instead",
),
on(
_Self = "std::cell::Cell<bool>",
any(_Self = "core::cell::Cell<bool>", _Self = "std::cell::Cell<bool>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` or `std::sync::atomic::AtomicBool` instead",
),
on(
_Self = "std::cell::Cell<T>",
any(_Self = "core::cell::Cell<T>", _Self = "std::cell::Cell<T>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock`",
),
on(
_Self = "std::cell::RefCell<T>",
any(_Self = "core::cell::RefCell<T>", _Self = "std::cell::RefCell<T>"),
note = "if you want to do aliasing and mutation between multiple threads, use `std::sync::RwLock` instead",
),
message = "`{Self}` cannot be shared between threads safely",

View file

@ -153,7 +153,7 @@ see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#ind
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),
on(
_Self = "std::string::String",
any(_Self = "alloc::string::String", _Self = "std::string::String"),
note = "you can use `.chars().nth()` or `.bytes().nth()`
see chapter in The Book <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"
),

View file

@ -226,8 +226,14 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::result::Result<T, E>",
R = "std::option::Option<std::convert::Infallible>"
any(
_Self = "core::result::Result<T, E>",
_Self = "std::result::Result<T, E>",
),
any(
R = "core::option::Option<core::convert::Infallible>",
R = "std::option::Option<std::convert::Infallible>",
)
),
message = "the `?` operator can only be used on `Result`s, not `Option`s, \
in {ItemContext} that returns `Result`",
@ -237,7 +243,10 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::result::Result<T, E>",
any(
_Self = "core::result::Result<T, E>",
_Self = "std::result::Result<T, E>",
)
),
// There's a special error message in the trait selection code for
// `From` in `?`, so this is not shown for result-in-result errors,
@ -250,8 +259,14 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::option::Option<T>",
R = "std::result::Result<T, E>",
any(
_Self = "core::option::Option<T>",
_Self = "std::option::Option<T>",
),
any(
R = "core::result::Result<T, E>",
R = "std::result::Result<T, E>",
)
),
message = "the `?` operator can only be used on `Option`s, not `Result`s, \
in {ItemContext} that returns `Option`",
@ -261,7 +276,10 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::option::Option<T>",
any(
_Self = "core::option::Option<T>",
_Self = "std::option::Option<T>",
)
),
// `Option`-in-`Option` always works, as there's only one possible
// residual, so this can also be phrased strongly.
@ -273,8 +291,14 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::ops::ControlFlow<B, C>",
R = "std::ops::ControlFlow<B, C>",
any(
_Self = "core::ops::ControlFlow<B, C>",
_Self = "std::ops::ControlFlow<B, C>",
),
any(
R = "core::ops::ControlFlow<B, C>",
R = "std::ops::ControlFlow<B, C>",
)
),
message = "the `?` operator in {ItemContext} that returns `ControlFlow<B, _>` \
can only be used on other `ControlFlow<B, _>`s (with the same Break type)",
@ -285,7 +309,10 @@ pub trait Try: FromResidual {
on(
all(
from_desugaring = "QuestionMark",
_Self = "std::ops::ControlFlow<B, C>",
any(
_Self = "core::ops::ControlFlow<B, C>",
_Self = "std::ops::ControlFlow<B, C>",
)
// `R` is not a `ControlFlow`, as that case was matched previously
),
message = "the `?` operator can only be used on `ControlFlow`s \

View file

@ -152,7 +152,10 @@ mod private_slice_index {
#[rustc_on_unimplemented(
on(T = "str", label = "string indices are ranges of `usize`",),
on(
all(any(T = "str", T = "&str", T = "std::string::String"), _Self = "{integer}"),
all(
any(T = "str", T = "&str", T = "alloc::string::String", T = "std::string::String"),
_Self = "{integer}"
),
note = "you can use `.chars().nth()` or `.bytes().nth()`\n\
for more information, see chapter 8 in The Book: \
<https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>"

View file

@ -186,6 +186,11 @@ For attributes with argument lists, format like functions.
```rust
#[repr(C)]
#[foo(foo, bar)]
#[long_multi_line_attribute(
split,
across,
lines,
)]
struct CRepr {
#![repr(C)]
x: f32,

View file

@ -288,7 +288,8 @@ and other assignment operators such as `+=` or `*=`).
For comparison operators, because for `T op U`, `&T op &U` is also implemented:
if you have `t: &T`, and `u: U`, prefer `*t op u` to `t op &u`. In general,
within expressions, prefer dereferencing to taking references.
within expressions, prefer dereferencing to taking references, unless necessary
(e.g. to avoid an unnecessarily expensive operation).
Use parentheses liberally, do not necessarily elide them due to precedence.
Tools should not automatically insert or remove parentheses. Do not use spaces

View file

@ -159,8 +159,8 @@ before the `else`.
If the initializer expression is multi-line, the `else` keyword and opening
brace of the block (i.e. `else {`) should be put on the same line as the end of
the initializer expression, with a space between them, if all the following are
true:
the initializer expression, with a space between them, if and only if all the
following are true:
* The initializer expression ends with one or more closing
parentheses, square brackets, and/or braces
@ -209,6 +209,28 @@ fn main() {
else {
return;
};
let LongStructName(AnotherStruct {
multi,
line,
pattern,
}) = slice.as_ref()
else {
return;
};
let LongStructName(AnotherStruct {
multi,
line,
pattern,
}) = multi_line_function_call(
arg1,
arg2,
arg3,
arg4,
) else {
return;
};
}
```

View file

@ -1,7 +1,7 @@
#![feature(inherent_associated_types)]
#![feature(type_privacy_lints)]
#![allow(incomplete_features)]
#![crate_type = "lib"]
#![deny(private_in_public)]
#![warn(private_interfaces)]

View file

@ -0,0 +1,11 @@
fn some_fn<'a>(_: &'a i32, _: impl FnOnce(&'a i32)) {}
fn main() {
let some_closure = |_| {};
for a in [1] {
some_fn(&a, |c| { //~ ERROR does not live long enough
some_closure(c);
});
}
}

View file

@ -0,0 +1,16 @@
error[E0597]: `a` does not live long enough
--> $DIR/issue-113087.rs:7:17
|
LL | for a in [1] {
| - binding `a` declared here
LL | some_fn(&a, |c| {
| ^^ borrowed value does not live long enough
LL | some_closure(c);
| ------------ borrow later captured here by closure
LL | });
LL | }
| - `a` dropped here while still borrowed
error: aborting due to previous error
For more information about this error, try `rustc --explain E0597`.

View file

@ -1,7 +1,7 @@
#![crate_type = "lib"]
#![feature(generic_const_exprs)]
#![feature(type_privacy_lints)]
#![allow(incomplete_features)]
#![warn(private_interfaces)]
// In this test both old and new private-in-public diagnostic were emitted.

View file

@ -1,3 +1,4 @@
#![feature(type_privacy_lints)]
#[warn(private_bounds)]
#[warn(private_interfaces)]

View file

@ -1,5 +1,5 @@
error[E0445]: private trait `Foo` in public interface
--> $DIR/E0445.rs:12:1
--> $DIR/E0445.rs:13:1
|
LL | trait Foo {
| --------- `Foo` declared as private
@ -10,23 +10,23 @@ LL | pub trait Bar : Foo {}
warning: trait `Foo` is more private than the item `Bar`
|
note: trait `Bar` is reachable at visibility `pub`
--> $DIR/E0445.rs:12:1
--> $DIR/E0445.rs:13:1
|
LL | pub trait Bar : Foo {}
| ^^^^^^^^^^^^^^^^^^^
note: but trait `Foo` is only usable at visibility `pub(crate)`
--> $DIR/E0445.rs:8:1
--> $DIR/E0445.rs:9:1
|
LL | trait Foo {
| ^^^^^^^^^
note: the lint level is defined here
--> $DIR/E0445.rs:1:8
--> $DIR/E0445.rs:2:8
|
LL | #[warn(private_bounds)]
| ^^^^^^^^^^^^^^
error[E0445]: private trait `Foo` in public interface
--> $DIR/E0445.rs:14:1
--> $DIR/E0445.rs:15:1
|
LL | trait Foo {
| --------- `Foo` declared as private
@ -37,18 +37,18 @@ LL | pub struct Bar2<T: Foo>(pub T);
warning: trait `Foo` is more private than the item `Bar2`
|
note: struct `Bar2` is reachable at visibility `pub`
--> $DIR/E0445.rs:14:1
--> $DIR/E0445.rs:15:1
|
LL | pub struct Bar2<T: Foo>(pub T);
| ^^^^^^^^^^^^^^^^^^^^^^^
note: but trait `Foo` is only usable at visibility `pub(crate)`
--> $DIR/E0445.rs:8:1
--> $DIR/E0445.rs:9:1
|
LL | trait Foo {
| ^^^^^^^^^
error[E0445]: private trait `Foo` in public interface
--> $DIR/E0445.rs:16:1
--> $DIR/E0445.rs:17:1
|
LL | trait Foo {
| --------- `Foo` declared as private
@ -59,12 +59,12 @@ LL | pub fn foo<T: Foo> (t: T) {}
warning: trait `Foo` is more private than the item `foo`
|
note: function `foo` is reachable at visibility `pub`
--> $DIR/E0445.rs:16:1
--> $DIR/E0445.rs:17:1
|
LL | pub fn foo<T: Foo> (t: T) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^
note: but trait `Foo` is only usable at visibility `pub(crate)`
--> $DIR/E0445.rs:8:1
--> $DIR/E0445.rs:9:1
|
LL | trait Foo {
| ^^^^^^^^^

View file

@ -0,0 +1,12 @@
// check-pass
#![warn(private_interfaces)] //~ WARN unknown lint
//~| WARN unknown lint
//~| WARN unknown lint
#![warn(private_bounds)] //~ WARN unknown lint
//~| WARN unknown lint
//~| WARN unknown lint
#![warn(unnameable_types)] //~ WARN unknown lint
//~| WARN unknown lint
//~| WARN unknown lint
fn main() {}

View file

@ -0,0 +1,93 @@
warning: unknown lint: `private_interfaces`
--> $DIR/feature-gate-type_privacy_lints.rs:3:1
|
LL | #![warn(private_interfaces)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `private_interfaces` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
= note: `#[warn(unknown_lints)]` on by default
warning: unknown lint: `private_bounds`
--> $DIR/feature-gate-type_privacy_lints.rs:6:1
|
LL | #![warn(private_bounds)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `private_bounds` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: unknown lint: `unnameable_types`
--> $DIR/feature-gate-type_privacy_lints.rs:9:1
|
LL | #![warn(unnameable_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `unnameable_types` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: unknown lint: `private_interfaces`
--> $DIR/feature-gate-type_privacy_lints.rs:3:1
|
LL | #![warn(private_interfaces)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `private_interfaces` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: unknown lint: `private_bounds`
--> $DIR/feature-gate-type_privacy_lints.rs:6:1
|
LL | #![warn(private_bounds)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `private_bounds` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: unknown lint: `unnameable_types`
--> $DIR/feature-gate-type_privacy_lints.rs:9:1
|
LL | #![warn(unnameable_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `unnameable_types` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: unknown lint: `private_interfaces`
--> $DIR/feature-gate-type_privacy_lints.rs:3:1
|
LL | #![warn(private_interfaces)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `private_interfaces` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: unknown lint: `private_bounds`
--> $DIR/feature-gate-type_privacy_lints.rs:6:1
|
LL | #![warn(private_bounds)]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `private_bounds` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: unknown lint: `unnameable_types`
--> $DIR/feature-gate-type_privacy_lints.rs:9:1
|
LL | #![warn(unnameable_types)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: the `unnameable_types` lint is unstable
= note: see issue #48054 <https://github.com/rust-lang/rust/issues/48054> for more information
= help: add `#![feature(type_privacy_lints)]` to the crate attributes to enable
warning: 9 warnings emitted

View file

@ -1,3 +1,4 @@
#![feature(type_privacy_lints)]
#![warn(private_bounds)]
// In this test both old and new private-in-public diagnostic were emitted.

View file

@ -1,5 +1,5 @@
error[E0445]: private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface
--> $DIR/issue-18389.rs:13:1
--> $DIR/issue-18389.rs:14:1
|
LL | trait Private<P, R> {
| ------------------- `Private<<Self as Public>::P, <Self as Public>::R>` declared as private
@ -14,7 +14,7 @@ LL | | > {
warning: trait `Private<<Self as Public>::P, <Self as Public>::R>` is more private than the item `Public`
|
note: trait `Public` is reachable at visibility `pub`
--> $DIR/issue-18389.rs:13:1
--> $DIR/issue-18389.rs:14:1
|
LL | / pub trait Public: Private<
LL | |
@ -23,12 +23,12 @@ LL | | <Self as Public>::R
LL | | > {
| |_^
note: but trait `Private<<Self as Public>::P, <Self as Public>::R>` is only usable at visibility `pub(crate)`
--> $DIR/issue-18389.rs:10:1
--> $DIR/issue-18389.rs:11:1
|
LL | trait Private<P, R> {
| ^^^^^^^^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/issue-18389.rs:1:9
--> $DIR/issue-18389.rs:2:9
|
LL | #![warn(private_bounds)]
| ^^^^^^^^^^^^^^

View file

@ -6,7 +6,7 @@ struct SemiPriv;
mod m {
#[rustc_effective_visibility]
struct Priv;
//~^ ERROR Direct: pub(self), Reexported: pub(self), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
//~^ ERROR not in the table
//~| ERROR not in the table
#[rustc_effective_visibility]

View file

@ -1,4 +1,4 @@
error: Direct: pub(self), Reexported: pub(self), Reachable: pub(crate), ReachableThroughImplTrait: pub(crate)
error: not in the table
--> $DIR/effective_visibilities_full_priv.rs:8:5
|
LL | struct Priv;

View file

@ -1,6 +1,6 @@
#![feature(auto_traits)]
#![feature(negative_impls)]
#![feature(type_privacy_lints)]
#![deny(private_interfaces)]
// In this test both old and new private-in-public diagnostic were emitted.

View file

@ -1,4 +1,4 @@
#![allow(unused)]
#![feature(type_privacy_lints)]
#![allow(private_in_public)]
#![deny(unnameable_types)]

View file

@ -3,8 +3,8 @@
#![crate_type = "lib"]
#![feature(generic_const_exprs)]
#![feature(type_privacy_lints)]
#![allow(incomplete_features)]
#![warn(private_bounds)]
#![warn(private_interfaces)]

View file

@ -2,8 +2,8 @@
#![crate_type = "lib"]
#![feature(generic_const_exprs)]
#![feature(type_privacy_lints)]
#![allow(incomplete_features)]
#![warn(private_bounds)]
// In this test both old and new private-in-public diagnostic were emitted.

View file

@ -1,3 +1,4 @@
#![feature(type_privacy_lints)]
#![allow(non_camel_case_types)] // genus is always capitalized
#![warn(private_interfaces)]
//~^ NOTE the lint level is defined here

View file

@ -1,5 +1,5 @@
error[E0446]: private type `Snail` in public interface
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:27:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:28:1
|
LL | pub(crate) struct Snail;
| ----------------------- `Snail` declared as private
@ -10,23 +10,23 @@ LL | pub type Helix_pomatia = Shell<Snail>;
warning: type `Snail` is more private than the item `Helix_pomatia`
|
note: type alias `Helix_pomatia` is reachable at visibility `pub`
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:27:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:28:1
|
LL | pub type Helix_pomatia = Shell<Snail>;
| ^^^^^^^^^^^^^^^^^^^^^^
note: but type `Snail` is only usable at visibility `pub(crate)`
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:9:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:10:1
|
LL | pub(crate) struct Snail;
| ^^^^^^^^^^^^^^^^^^^^^^^
note: the lint level is defined here
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:2:9
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:3:9
|
LL | #![warn(private_interfaces)]
| ^^^^^^^^^^^^^^^^^^
error[E0446]: crate-private type `Turtle` in public interface
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:31:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:32:1
|
LL | pub(super) struct Turtle;
| ------------------------ `Turtle` declared as crate-private
@ -37,18 +37,18 @@ LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>;
warning: type `Turtle` is more private than the item `Dermochelys_coriacea`
|
note: type alias `Dermochelys_coriacea` is reachable at visibility `pub`
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:31:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:32:1
|
LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: but type `Turtle` is only usable at visibility `pub(crate)`
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:14:5
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:15:5
|
LL | pub(super) struct Turtle;
| ^^^^^^^^^^^^^^^^^^^^^^^^
error[E0446]: private type `Tortoise` in public interface
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:35:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:36:1
|
LL | struct Tortoise;
| --------------- `Tortoise` declared as private
@ -59,12 +59,12 @@ LL | pub type Testudo_graeca = Shell<Tortoise>;
warning: type `Tortoise` is more private than the item `Testudo_graeca`
|
note: type alias `Testudo_graeca` is reachable at visibility `pub`
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:35:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:36:1
|
LL | pub type Testudo_graeca = Shell<Tortoise>;
| ^^^^^^^^^^^^^^^^^^^^^^^
note: but type `Tortoise` is only usable at visibility `pub(crate)`
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:19:1
--> $DIR/issue-33174-restricted-type-in-public-interface.rs:20:1
|
LL | struct Tortoise;
| ^^^^^^^^^^^^^^^

View file

@ -0,0 +1 @@
pub trait Trait {}

View file

@ -0,0 +1,3 @@
pub trait Trait {}
impl Trait for () {}

View file

@ -0,0 +1,18 @@
//! This test checks that we do need to implement
//! all members, even if their where bounds only hold
//! due to other impls.
trait Foo<T> {
fn foo()
where
Self: Foo<()>;
}
impl Foo<()> for () {
fn foo() {}
}
impl Foo<u32> for () {}
//~^ ERROR: not all trait items implemented, missing: `foo`
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl.rs:15:1
|
LL | / fn foo()
LL | | where
LL | | Self: Foo<()>;
| |______________________- `foo` from trait
...
LL | impl Foo<u32> for () {}
| ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to previous error
For more information about this error, try `rustc --explain E0046`.

View file

@ -0,0 +1,13 @@
//! This test checks that we currently need to implement
//! members, even if their where bounds don't hold for the impl type.
trait Foo<T> {
fn foo()
where
Self: Foo<()>;
}
impl Foo<u32> for () {}
//~^ ERROR: not all trait items implemented, missing: `foo`
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl2.rs:10:1
|
LL | / fn foo()
LL | | where
LL | | Self: Foo<()>;
| |______________________- `foo` from trait
...
LL | impl Foo<u32> for () {}
| ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to previous error
For more information about this error, try `rustc --explain E0046`.

View file

@ -0,0 +1,19 @@
//! Check that we don't break orphan rules.
//! The dependency may add an impl for `u8` later,
//! which would break this crate. We want to avoid adding
//! more ways in which adding an impl can be a breaking change.
// aux-build:trivial3.rs
extern crate trivial3;
pub trait Foo {
fn foo()
where
Self: trivial3::Trait;
}
impl Foo for u8 {}
//~^ ERROR not all trait items implemented, missing: `foo`
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl3.rs:16:1
|
LL | / fn foo()
LL | | where
LL | | Self: trivial3::Trait;
| |______________________________- `foo` from trait
...
LL | impl Foo for u8 {}
| ^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to previous error
For more information about this error, try `rustc --explain E0046`.

View file

@ -0,0 +1,21 @@
//! Check that we don't break orphan rules.
//! The dependency may add an impl for `u8` later,
//! which would break this crate. We want to avoid adding
//! more ways in which adding an impl can be a breaking change.
//! This test differs from `trivial_impl3` because there actually
//! exists any impl for `Trait`, which has an effect on coherence.
// aux-build:trivial4.rs
extern crate trivial4;
pub trait Foo {
fn foo()
where
Self: trivial4::Trait;
}
impl Foo for u8 {}
//~^ ERROR not all trait items implemented, missing: `foo`
fn main() {}

View file

@ -0,0 +1,14 @@
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl4.rs:18:1
|
LL | / fn foo()
LL | | where
LL | | Self: trivial4::Trait;
| |______________________________- `foo` from trait
...
LL | impl Foo for u8 {}
| ^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to previous error
For more information about this error, try `rustc --explain E0046`.

View file

@ -0,0 +1,26 @@
//! This test checks that we currently need to implement
//! members, even if their where bounds don't hold for the impl type.
trait Foo {
fn foo()
where
Self: Sized;
}
impl Foo for () {
fn foo() {}
}
// Must not be allowed
impl Foo for i32 {}
//~^ ERROR: not all trait items implemented, missing: `foo`
// Should be allowed
impl Foo for dyn std::fmt::Debug {}
//~^ ERROR: not all trait items implemented, missing: `foo`
impl Foo for dyn std::fmt::Display {
fn foo() {}
}
fn main() {}

View file

@ -0,0 +1,25 @@
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl_sized.rs:15:1
|
LL | / fn foo()
LL | | where
LL | | Self: Sized;
| |____________________- `foo` from trait
...
LL | impl Foo for i32 {}
| ^^^^^^^^^^^^^^^^ missing `foo` in implementation
error[E0046]: not all trait items implemented, missing: `foo`
--> $DIR/trivial_impl_sized.rs:19:1
|
LL | / fn foo()
LL | | where
LL | | Self: Sized;
| |____________________- `foo` from trait
...
LL | impl Foo for dyn std::fmt::Debug {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0046`.