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:
commit
0a32ca9831
47 changed files with 569 additions and 204 deletions
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -1558,6 +1558,7 @@ symbols! {
|
|||
type_length_limit,
|
||||
type_macros,
|
||||
type_name,
|
||||
type_privacy_lints,
|
||||
u128,
|
||||
u16,
|
||||
u32,
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>"
|
||||
),
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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>"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
|
|
|
@ -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)]
|
||||
|
||||
|
|
11
tests/ui/closures/issue-113087.rs
Normal file
11
tests/ui/closures/issue-113087.rs
Normal 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);
|
||||
});
|
||||
}
|
||||
}
|
16
tests/ui/closures/issue-113087.stderr
Normal file
16
tests/ui/closures/issue-113087.stderr
Normal 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`.
|
|
@ -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.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#![feature(type_privacy_lints)]
|
||||
#[warn(private_bounds)]
|
||||
#[warn(private_interfaces)]
|
||||
|
||||
|
|
|
@ -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 {
|
||||
| ^^^^^^^^^
|
||||
|
|
12
tests/ui/feature-gates/feature-gate-type_privacy_lints.rs
Normal file
12
tests/ui/feature-gates/feature-gate-type_privacy_lints.rs
Normal 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() {}
|
|
@ -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
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
#![feature(type_privacy_lints)]
|
||||
#![warn(private_bounds)]
|
||||
|
||||
// In this test both old and new private-in-public diagnostic were emitted.
|
||||
|
|
|
@ -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)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![allow(unused)]
|
||||
#![feature(type_privacy_lints)]
|
||||
#![allow(private_in_public)]
|
||||
#![deny(unnameable_types)]
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
#![crate_type = "lib"]
|
||||
#![feature(generic_const_exprs)]
|
||||
#![feature(type_privacy_lints)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
#![warn(private_bounds)]
|
||||
#![warn(private_interfaces)]
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
1
tests/ui/traits/auxiliary/trivial3.rs
Normal file
1
tests/ui/traits/auxiliary/trivial3.rs
Normal file
|
@ -0,0 +1 @@
|
|||
pub trait Trait {}
|
3
tests/ui/traits/auxiliary/trivial4.rs
Normal file
3
tests/ui/traits/auxiliary/trivial4.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
pub trait Trait {}
|
||||
|
||||
impl Trait for () {}
|
18
tests/ui/traits/trivial_impl.rs
Normal file
18
tests/ui/traits/trivial_impl.rs
Normal 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() {}
|
14
tests/ui/traits/trivial_impl.stderr
Normal file
14
tests/ui/traits/trivial_impl.stderr
Normal 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`.
|
13
tests/ui/traits/trivial_impl2.rs
Normal file
13
tests/ui/traits/trivial_impl2.rs
Normal 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() {}
|
14
tests/ui/traits/trivial_impl2.stderr
Normal file
14
tests/ui/traits/trivial_impl2.stderr
Normal 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`.
|
19
tests/ui/traits/trivial_impl3.rs
Normal file
19
tests/ui/traits/trivial_impl3.rs
Normal 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() {}
|
14
tests/ui/traits/trivial_impl3.stderr
Normal file
14
tests/ui/traits/trivial_impl3.stderr
Normal 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`.
|
21
tests/ui/traits/trivial_impl4.rs
Normal file
21
tests/ui/traits/trivial_impl4.rs
Normal 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() {}
|
14
tests/ui/traits/trivial_impl4.stderr
Normal file
14
tests/ui/traits/trivial_impl4.stderr
Normal 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`.
|
26
tests/ui/traits/trivial_impl_sized.rs
Normal file
26
tests/ui/traits/trivial_impl_sized.rs
Normal 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() {}
|
25
tests/ui/traits/trivial_impl_sized.stderr
Normal file
25
tests/ui/traits/trivial_impl_sized.stderr
Normal 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`.
|
Loading…
Add table
Reference in a new issue