diff options
62 files changed, 1576 insertions, 365 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 04ed2767876..a0979bbda54 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -364,7 +364,12 @@ impl<'a> AstValidator<'a> { self.err_handler().emit_err(errors::BoundInContext { span, ctx }); } - fn check_foreign_ty_genericless(&self, generics: &Generics, where_span: Span) { + fn check_foreign_ty_genericless( + &self, + generics: &Generics, + before_where_clause: &TyAliasWhereClause, + after_where_clause: &TyAliasWhereClause, + ) { let cannot_have = |span, descr, remove_descr| { self.err_handler().emit_err(errors::ExternTypesCannotHave { span, @@ -378,9 +383,14 @@ impl<'a> AstValidator<'a> { cannot_have(generics.span, "generic parameters", "generic parameters"); } - if !generics.where_clause.predicates.is_empty() { - cannot_have(where_span, "`where` clauses", "`where` clause"); - } + let check_where_clause = |where_clause: &TyAliasWhereClause| { + if let TyAliasWhereClause(true, where_clause_span) = where_clause { + cannot_have(*where_clause_span, "`where` clauses", "`where` clause"); + } + }; + + check_where_clause(before_where_clause); + check_where_clause(after_where_clause); } fn check_foreign_kind_bodyless(&self, ident: Ident, kind: &str, body: Option<Span>) { @@ -1039,7 +1049,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_defaultness(fi.span, *defaultness); self.check_foreign_kind_bodyless(fi.ident, "type", ty.as_ref().map(|b| b.span)); self.check_type_no_bounds(bounds, "`extern` blocks"); - self.check_foreign_ty_genericless(generics, where_clauses.0.1); + self.check_foreign_ty_genericless(generics, &where_clauses.0, &where_clauses.1); self.check_foreign_item_ascii_only(fi.ident); } ForeignItemKind::Static(_, _, body) => { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index a269a7a1d8b..4554d167080 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1449,7 +1449,7 @@ fn check_fn_or_method<'tcx>( let span = tcx.def_span(def_id); let has_implicit_self = hir_decl.implicit_self != hir::ImplicitSelfKind::None; let mut inputs = sig.inputs().iter().skip(if has_implicit_self { 1 } else { 0 }); - // Check that the argument is a tuple + // Check that the argument is a tuple and is sized if let Some(ty) = inputs.next() { wfcx.register_bound( ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall), @@ -1457,6 +1457,12 @@ fn check_fn_or_method<'tcx>( *ty, tcx.require_lang_item(hir::LangItem::Tuple, Some(span)), ); + wfcx.register_bound( + ObligationCause::new(span, wfcx.body_def_id, ObligationCauseCode::RustCall), + wfcx.param_env, + *ty, + tcx.require_lang_item(hir::LangItem::Sized, Some(span)), + ); } else { tcx.sess.span_err( hir_decl.inputs.last().map_or(span, |input| input.span), diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl index 4728edd837a..c1c58db5764 100644 --- a/compiler/rustc_hir_typeck/messages.ftl +++ b/compiler/rustc_hir_typeck/messages.ftl @@ -89,6 +89,8 @@ hir_typeck_suggest_boxing_note = for more on the distinction between the stack a hir_typeck_suggest_boxing_when_appropriate = store this in the heap by calling `Box::new` +hir_typeck_suggest_ptr_null_mut = consider using `core::ptr::null_mut` instead + hir_typeck_union_pat_dotdot = `..` cannot be used in union patterns hir_typeck_union_pat_multiple_fields = union patterns should have exactly one field diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 4389ad6ef26..9da72aae776 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -470,6 +470,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx.require_lang_item(hir::LangItem::Tuple, Some(sp)), traits::ObligationCause::new(sp, self.body_id, traits::RustCall), ); + self.require_type_is_sized(ty, sp, traits::RustCall); } else { self.tcx.sess.span_err( sp, diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 5161a366ae7..6b4168d8944 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -298,6 +298,17 @@ pub enum SuggestBoxing { }, } +#[derive(Subdiagnostic)] +#[suggestion( + hir_typeck_suggest_ptr_null_mut, + applicability = "maybe-incorrect", + code = "core::ptr::null_mut()" +)] +pub struct SuggestPtrNullMut { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(hir_typeck_no_associated_item, code = "E0599")] pub struct NoAssociatedItem { diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index f03c7ca44ba..3f6847be91b 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2871,6 +2871,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } + + if base_t.is_unsafe_ptr() && idx_t.is_integral() { + err.multipart_suggestion( + "consider using `wrapping_add` or `add` for indexing into raw pointer", + vec![ + (base.span.between(idx.span), ".wrapping_add(".to_owned()), + ( + idx.span.shrink_to_hi().until(expr.span.shrink_to_hi()), + ")".to_owned(), + ), + ], + Applicability::MaybeIncorrect, + ); + } + let reported = err.emit(); self.tcx.ty_error(reported) } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 48c3d6f08de..4a3e28ffce9 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1,4 +1,5 @@ use crate::coercion::CoerceMany; +use crate::errors::SuggestPtrNullMut; use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx}; use crate::gather_locals::Declaration; use crate::method::MethodCallee; @@ -814,6 +815,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } + self.suggest_ptr_null_mut( + expected_ty, + provided_ty, + provided_args[*provided_idx], + &mut err, + ); + // Call out where the function is defined self.label_fn_like( &mut err, @@ -1271,6 +1279,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.emit(); } + fn suggest_ptr_null_mut( + &self, + expected_ty: Ty<'tcx>, + provided_ty: Ty<'tcx>, + arg: &hir::Expr<'tcx>, + err: &mut rustc_errors::DiagnosticBuilder<'tcx, ErrorGuaranteed>, + ) { + if let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Mut, .. }) = expected_ty.kind() + && let ty::RawPtr(ty::TypeAndMut { mutbl: hir::Mutability::Not, .. }) = provided_ty.kind() + && let hir::ExprKind::Call(callee, _) = arg.kind + && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = callee.kind + && let Res::Def(_, def_id) = path.res + && self.tcx.get_diagnostic_item(sym::ptr_null) == Some(def_id) + { + // The user provided `ptr::null()`, but the function expects + // `ptr::null_mut()`. + err.subdiagnostic(SuggestPtrNullMut { + span: arg.span + }); + } + } + // AST fragment checking pub(in super::super) fn check_lit( &self, diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index b8bf2b69120..4f3d1d45679 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -521,6 +521,52 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } + + // Suggest using `add`, `offset` or `offset_from` for pointer - {integer}, + // pointer + {integer} or pointer - pointer. + if op.span.can_be_used_for_suggestions() { + match op.node { + hir::BinOpKind::Add if lhs_ty.is_unsafe_ptr() && rhs_ty.is_integral() => { + err.multipart_suggestion( + "consider using `wrapping_add` or `add` for pointer + {integer}", + vec![ + ( + lhs_expr.span.between(rhs_expr.span), + ".wrapping_add(".to_owned(), + ), + (rhs_expr.span.shrink_to_hi(), ")".to_owned()), + ], + Applicability::MaybeIncorrect, + ); + } + hir::BinOpKind::Sub => { + if lhs_ty.is_unsafe_ptr() && rhs_ty.is_integral() { + err.multipart_suggestion( + "consider using `wrapping_sub` or `sub` for pointer - {integer}", + vec![ + (lhs_expr.span.between(rhs_expr.span), ".wrapping_sub(".to_owned()), + (rhs_expr.span.shrink_to_hi(), ")".to_owned()), + ], + Applicability::MaybeIncorrect + ); + } + + if lhs_ty.is_unsafe_ptr() && rhs_ty.is_unsafe_ptr() { + err.multipart_suggestion( + "consider using `offset_from` for pointer - pointer if the pointers point to the same allocation", + vec![ + (lhs_expr.span.shrink_to_lo(), "unsafe { ".to_owned()), + (lhs_expr.span.between(rhs_expr.span), ".offset_from(".to_owned()), + (rhs_expr.span.shrink_to_hi(), ") }".to_owned()), + ], + Applicability::MaybeIncorrect + ); + } + } + _ => {} + } + } + let reported = err.emit(); self.tcx.ty_error(reported) } diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index 7a80ee98cb3..bb2bd2faec2 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -34,7 +34,7 @@ use rustc_middle::infer::unify_key::{ConstVarValue, ConstVariableValue}; use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKind}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::relate::{RelateResult, TypeRelation}; -use rustc_middle::ty::{self, AliasKind, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, InferConst, ToPredicate, Ty, TyCtxt, TypeVisitableExt}; use rustc_middle::ty::{IntType, UintType}; use rustc_span::DUMMY_SP; @@ -103,12 +103,12 @@ impl<'tcx> InferCtxt<'tcx> { // We don't expect `TyVar` or `Fresh*` vars at this point with lazy norm. ( - ty::Alias(AliasKind::Projection, _), + ty::Alias(..), ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), ) | ( ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)), - ty::Alias(AliasKind::Projection, _), + ty::Alias(..), ) if self.next_trait_solver() => { bug!() } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index eb246c3f93e..53ece08ac3d 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3372,7 +3372,9 @@ declare_lint_pass! { OVERLAPPING_RANGE_ENDPOINTS, PATTERNS_IN_FNS_WITHOUT_BODY, POINTER_STRUCTURAL_MATCH, + PRIVATE_BOUNDS, PRIVATE_IN_PUBLIC, + PRIVATE_INTERFACES, PROC_MACRO_BACK_COMPAT, PROC_MACRO_DERIVE_RESOLUTION_FALLBACK, PUB_USE_OF_PRIVATE_EXTERN_CRATE, @@ -3399,6 +3401,7 @@ declare_lint_pass! { UNINHABITED_STATIC, UNKNOWN_CRATE_TYPES, UNKNOWN_LINTS, + UNNAMEABLE_TYPES, UNREACHABLE_CODE, UNREACHABLE_PATTERNS, UNSAFE_OP_IN_UNSAFE_FN, @@ -4251,3 +4254,95 @@ declare_lint! { Warn, "\"invalid_parameter\" isn't a valid argument for `#[macro_export]`", } + +declare_lint! { + /// The `private_interfaces` lint detects types in a primary interface of an item, + /// that are more private than the item itself. Primary interface of an item is all + /// its interface except for bounds on generic parameters and where clauses. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # #![allow(unused)] + /// # #![allow(private_in_public)] + /// #![deny(private_interfaces)] + /// struct SemiPriv; + /// + /// mod m1 { + /// struct Priv; + /// impl crate::SemiPriv { + /// pub fn f(_: Priv) {} + /// } + /// } + /// + /// # fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Having something private in primary interface guarantees that + /// the item will be unusable from outer modules due to type privacy. + pub PRIVATE_INTERFACES, + Allow, + "private type in primary interface of an item", +} + +declare_lint! { + /// The `private_bounds` lint detects types in a secondary interface of an item, + /// that are more private than the item itself. Secondary interface of an item consists of + /// bounds on generic parameters and where clauses, including supertraits for trait items. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # #![allow(private_in_public)] + /// # #![allow(unused)] + /// #![deny(private_bounds)] + /// + /// struct PrivTy; + /// pub struct S + /// where PrivTy: + /// {} + /// # fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Having private types or traits in item bounds makes it less clear what interface + /// the item actually provides. + pub PRIVATE_BOUNDS, + Allow, + "private type in secondary interface of an item" +} + +declare_lint! { + /// The `unnameable_types` lint detects types for which you can get objects of that type, + /// but cannot name the type itself. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// # #![allow(unused)] + /// #![deny(unnameable_types)] + /// mod m { + /// pub struct S; + /// } + /// + /// pub fn get_voldemort() -> m::S { m::S } + /// # fn main() {} + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// It is often expected that if you can obtain an object of type `T`, then + /// 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" +} diff --git a/compiler/rustc_privacy/messages.ftl b/compiler/rustc_privacy/messages.ftl index b68e8a78aab..6f51981cf09 100644 --- a/compiler/rustc_privacy/messages.ftl +++ b/compiler/rustc_privacy/messages.ftl @@ -17,7 +17,14 @@ privacy_private_in_public_lint = *[other] E0446 }) +privacy_private_interface_or_bounds_lint = {$ty_kind} `{$ty_descr}` is more private than the item `{$item_descr}` + .item_note = {$item_kind} `{$item_descr}` is reachable at visibility `{$item_vis_descr}` + .ty_note = but {$ty_kind} `{$ty_descr}` is only usable at visibility `{$ty_vis_descr}` + privacy_report_effective_visibility = {$descr} +privacy_unnameable_types_lint = {$kind} `{$descr}` is reachable but cannot be named + .label = reachable at visibility `{$reachable_vis}`, but can only be named at visibility `{$reexported_vis}` + privacy_unnamed_item_is_private = {$kind} is private .label = private {$kind} diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs index 72b53eefa08..67689b5e713 100644 --- a/compiler/rustc_privacy/src/errors.rs +++ b/compiler/rustc_privacy/src/errors.rs @@ -98,3 +98,32 @@ pub struct PrivateInPublicLint<'a> { pub kind: &'a str, pub descr: DiagnosticArgFromDisplay<'a>, } + +#[derive(LintDiagnostic)] +#[diag(privacy_unnameable_types_lint)] +pub struct UnnameableTypesLint<'a> { + #[label] + pub span: Span, + pub kind: &'a str, + pub descr: DiagnosticArgFromDisplay<'a>, + pub reachable_vis: &'a str, + pub reexported_vis: &'a str, +} + +// Used for `private_interfaces` and `private_bounds` lints. +// They will replace private-in-public errors and compatibility lints in future. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html for more details. +#[derive(LintDiagnostic)] +#[diag(privacy_private_interface_or_bounds_lint)] +pub struct PrivateInterfacesOrBoundsLint<'a> { + #[note(privacy_item_note)] + pub item_span: Span, + pub item_kind: &'a str, + pub item_descr: DiagnosticArgFromDisplay<'a>, + pub item_vis_descr: &'a str, + #[note(privacy_ty_note)] + pub ty_span: Span, + pub ty_kind: &'a str, + pub ty_descr: DiagnosticArgFromDisplay<'a>, + pub ty_vis_descr: &'a str, +} diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index afd32e38d5b..a51a1c9a8a4 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -22,7 +22,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{AssocItemKind, HirIdSet, ItemId, Node, PatKind}; +use rustc_hir::{AssocItemKind, ForeignItemKind, HirIdSet, ItemId, Node, PatKind}; use rustc_middle::bug; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::{EffectiveVisibilities, EffectiveVisibility, Level}; @@ -42,8 +42,8 @@ use std::{fmt, mem}; use errors::{ FieldIsPrivate, FieldIsPrivateLabel, FromPrivateDependencyInPublicInterface, InPublicInterface, - InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, ReportEffectiveVisibility, - UnnamedItemIsPrivate, + InPublicInterfaceTraits, ItemIsPrivate, PrivateInPublicLint, PrivateInterfacesOrBoundsLint, + ReportEffectiveVisibility, UnnameableTypesLint, UnnamedItemIsPrivate, }; fluent_messages! { "../messages.ftl" } @@ -52,6 +52,17 @@ fluent_messages! { "../messages.ftl" } /// Generic infrastructure used to implement specific visitors below. //////////////////////////////////////////////////////////////////////////////// +struct LazyDefPathStr<'tcx> { + def_id: DefId, + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.tcx.def_path_str(self.def_id)) + } +} + /// Implemented to visit all `DefId`s in a type. /// Visiting `DefId`s is useful because visibilities and reachabilities are attached to them. /// The idea is to visit "all components of a type", as documented in @@ -259,16 +270,6 @@ where &LazyDefPathStr { def_id: data.def_id, tcx }, )?; - struct LazyDefPathStr<'tcx> { - def_id: DefId, - tcx: TyCtxt<'tcx>, - } - impl<'tcx> fmt::Display for LazyDefPathStr<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.tcx.def_path_str(self.def_id)) - } - } - // This will also visit substs if necessary, so we don't need to recurse. return if self.def_id_visitor.shallow() { ControlFlow::Continue(()) @@ -409,8 +410,25 @@ impl VisibilityLike for ty::Visibility { } } -impl VisibilityLike for EffectiveVisibility { - const MAX: Self = EffectiveVisibility::from_vis(ty::Visibility::Public); +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> { ... }` @@ -429,7 +447,7 @@ impl VisibilityLike for EffectiveVisibility { EffectiveVisibility::from_vis(private_vis) }); - effective_vis.min(find.min, find.tcx) + ShallowEffectiveVis(effective_vis.min(find.min.0, find.tcx)) } } @@ -767,11 +785,13 @@ impl<'tcx> Visitor<'tcx> for EmbargoVisitor<'tcx> { } } hir::ItemKind::Impl(ref impl_) => { - let item_ev = EffectiveVisibility::of_impl( + let item_ev = ShallowEffectiveVis::of_impl( 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); self.reach(item.owner_id.def_id, item_ev).generics().predicates().ty().trait_ref(); @@ -912,6 +932,21 @@ pub struct TestReachabilityVisitor<'tcx, 'a> { effective_visibilities: &'a EffectiveVisibilities, } +fn vis_to_string<'tcx>(def_id: LocalDefId, vis: ty::Visibility, tcx: TyCtxt<'tcx>) -> String { + match vis { + ty::Visibility::Restricted(restricted_id) => { + if restricted_id.is_top_level_module() { + "pub(crate)".to_string() + } else if restricted_id == tcx.parent_module_from_def_id(def_id) { + "pub(self)".to_string() + } else { + format!("pub({})", tcx.item_name(restricted_id.to_def_id())) + } + } + ty::Visibility::Public => "pub".to_string(), + } +} + impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { fn effective_visibility_diagnostic(&mut self, def_id: LocalDefId) { if self.tcx.has_attr(def_id, sym::rustc_effective_visibility) { @@ -919,18 +954,7 @@ impl<'tcx, 'a> TestReachabilityVisitor<'tcx, 'a> { let span = self.tcx.def_span(def_id.to_def_id()); if let Some(effective_vis) = self.effective_visibilities.effective_vis(def_id) { for level in Level::all_levels() { - let vis_str = match effective_vis.at_level(level) { - ty::Visibility::Restricted(restricted_id) => { - if restricted_id.is_top_level_module() { - "pub(crate)".to_string() - } else if *restricted_id == self.tcx.parent_module_from_def_id(def_id) { - "pub(self)".to_string() - } else { - format!("pub({})", self.tcx.item_name(restricted_id.to_def_id())) - } - } - ty::Visibility::Public => "pub".to_string(), - }; + let vis_str = vis_to_string(def_id, *effective_vis.at_level(level), self.tcx); if level != Level::Direct { error_msg.push_str(", "); } @@ -1745,12 +1769,15 @@ struct SearchInterfaceForPrivateItemsVisitor<'tcx> { item_def_id: LocalDefId, /// The visitor checks that each component type is at least this visible. required_visibility: ty::Visibility, + required_effective_vis: Option<EffectiveVisibility>, has_old_errors: bool, in_assoc_ty: bool, + in_primary_interface: bool, } impl SearchInterfaceForPrivateItemsVisitor<'_> { fn generics(&mut self) -> &mut Self { + self.in_primary_interface = true; for param in &self.tcx.generics_of(self.item_def_id).params { match param.kind { GenericParamDefKind::Lifetime => {} @@ -1769,6 +1796,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } fn predicates(&mut self) -> &mut Self { + self.in_primary_interface = false; // N.B., we use `explicit_predicates_of` and not `predicates_of` // because we don't want to report privacy errors due to where // clauses that the compiler inferred. We only want to @@ -1780,6 +1808,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } fn bounds(&mut self) -> &mut Self { + self.in_primary_interface = false; self.visit_predicates(ty::GenericPredicates { parent: None, predicates: self.tcx.explicit_item_bounds(self.item_def_id).skip_binder(), @@ -1788,6 +1817,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } fn ty(&mut self) -> &mut Self { + self.in_primary_interface = true; self.visit(self.tcx.type_of(self.item_def_id).subst_identity()); self } @@ -1811,8 +1841,10 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { }; let vis = self.tcx.local_visibility(local_def_id); + let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); + let span = self.tcx.def_span(self.item_def_id.to_def_id()); + let vis_span = self.tcx.def_span(def_id); if !vis.is_at_least(self.required_visibility, self.tcx) { - let hir_id = self.tcx.hir().local_def_id_to_hir_id(local_def_id); let vis_descr = match vis { ty::Visibility::Public => "public", ty::Visibility::Restricted(vis_def_id) => { @@ -1825,12 +1857,11 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } } }; - let span = self.tcx.def_span(self.item_def_id.to_def_id()); + if self.has_old_errors || self.in_assoc_ty || self.tcx.resolutions(()).has_pub_restricted { - let vis_span = self.tcx.def_span(def_id); if kind == "trait" { self.tcx.sess.emit_err(InPublicInterfaceTraits { span, @@ -1858,6 +1889,39 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> { } } + let Some(effective_vis) = self.required_effective_vis else { + return false; + }; + + // FIXME: `Level::Reachable` should be taken instead of `Level::Reexported` + let reexported_at_vis = *effective_vis.at_level(Level::Reexported); + + if !vis.is_at_least(reexported_at_vis, self.tcx) { + let lint = if self.in_primary_interface { + lint::builtin::PRIVATE_INTERFACES + } else { + lint::builtin::PRIVATE_BOUNDS + }; + self.tcx.emit_lint( + lint, + hir_id, + PrivateInterfacesOrBoundsLint { + item_span: span, + item_kind: self.tcx.def_descr(self.item_def_id.to_def_id()), + item_descr: (&LazyDefPathStr { + def_id: self.item_def_id.to_def_id(), + tcx: self.tcx, + }) + .into(), + item_vis_descr: &vis_to_string(self.item_def_id, reexported_at_vis, self.tcx), + ty_span: vis_span, + ty_kind: kind, + ty_descr: descr.into(), + ty_vis_descr: &vis_to_string(local_def_id, vis, self.tcx), + }, + ); + } + false } @@ -1891,25 +1955,55 @@ impl<'tcx> DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> { } } -struct PrivateItemsInPublicInterfacesChecker<'tcx> { +struct PrivateItemsInPublicInterfacesChecker<'tcx, 'a> { tcx: TyCtxt<'tcx>, old_error_set_ancestry: HirIdSet, + effective_visibilities: &'a EffectiveVisibilities, } -impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { +impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { fn check( &self, def_id: LocalDefId, required_visibility: ty::Visibility, + required_effective_vis: Option<EffectiveVisibility>, ) -> SearchInterfaceForPrivateItemsVisitor<'tcx> { SearchInterfaceForPrivateItemsVisitor { tcx: self.tcx, item_def_id: def_id, required_visibility, + required_effective_vis, has_old_errors: self .old_error_set_ancestry .contains(&self.tcx.hir().local_def_id_to_hir_id(def_id)), in_assoc_ty: false, + in_primary_interface: true, + } + } + + fn check_unnameable(&self, def_id: LocalDefId, effective_vis: Option<EffectiveVisibility>) { + let Some(effective_vis) = effective_vis else { + return; + }; + + let reexported_at_vis = effective_vis.at_level(Level::Reexported); + let reachable_at_vis = effective_vis.at_level(Level::Reachable); + + if reexported_at_vis != reachable_at_vis { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); + let span = self.tcx.def_span(def_id.to_def_id()); + self.tcx.emit_spanned_lint( + lint::builtin::UNNAMEABLE_TYPES, + hir_id, + span, + UnnameableTypesLint { + span, + kind: self.tcx.def_descr(def_id.to_def_id()), + descr: (&LazyDefPathStr { def_id: def_id.to_def_id(), tcx: self.tcx }).into(), + reachable_vis: &vis_to_string(def_id, *reachable_at_vis, self.tcx), + reexported_vis: &vis_to_string(def_id, *reexported_at_vis, self.tcx), + }, + ); } } @@ -1918,13 +2012,19 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { def_id: LocalDefId, assoc_item_kind: AssocItemKind, vis: ty::Visibility, + effective_vis: Option<EffectiveVisibility>, ) { - let mut check = self.check(def_id, vis); + let mut check = self.check(def_id, vis, effective_vis); let (check_ty, is_assoc_ty) = match assoc_item_kind { AssocItemKind::Const | AssocItemKind::Fn { .. } => (true, false), AssocItemKind::Type => (self.tcx.defaultness(def_id).has_value(), true), }; + + if is_assoc_ty { + self.check_unnameable(def_id, self.get(def_id)); + } + check.in_assoc_ty = is_assoc_ty; check.generics().predicates(); if check_ty { @@ -1932,50 +2032,72 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { } } + fn get(&self, def_id: LocalDefId) -> Option<EffectiveVisibility> { + self.effective_visibilities.effective_vis(def_id).copied() + } + pub fn check_item(&mut self, id: ItemId) { let tcx = self.tcx; let def_id = id.owner_id.def_id; let item_visibility = tcx.local_visibility(def_id); + let effective_vis = self.get(def_id); let def_kind = tcx.def_kind(def_id); match def_kind { DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { - self.check(def_id, item_visibility).generics().predicates().ty(); + if let DefKind::TyAlias = def_kind { + self.check_unnameable(def_id, effective_vis); + } + self.check(def_id, item_visibility, effective_vis).generics().predicates().ty(); } DefKind::OpaqueTy => { // `ty()` for opaque types is the underlying type, // it's not a part of interface, so we skip it. - self.check(def_id, item_visibility).generics().bounds(); + self.check(def_id, item_visibility, effective_vis).generics().bounds(); } DefKind::Trait => { let item = tcx.hir().item(id); if let hir::ItemKind::Trait(.., trait_item_refs) = item.kind { - self.check(item.owner_id.def_id, item_visibility).generics().predicates(); + self.check_unnameable(item.owner_id.def_id, effective_vis); + + self.check(item.owner_id.def_id, item_visibility, effective_vis) + .generics() + .predicates(); for trait_item_ref in trait_item_refs { self.check_assoc_item( trait_item_ref.id.owner_id.def_id, trait_item_ref.kind, item_visibility, + effective_vis, ); if let AssocItemKind::Type = trait_item_ref.kind { - self.check(trait_item_ref.id.owner_id.def_id, item_visibility).bounds(); + self.check( + trait_item_ref.id.owner_id.def_id, + item_visibility, + effective_vis, + ) + .bounds(); } } } } DefKind::TraitAlias => { - self.check(def_id, item_visibility).generics().predicates(); + self.check(def_id, item_visibility, effective_vis).generics().predicates(); } DefKind::Enum => { let item = tcx.hir().item(id); if let hir::ItemKind::Enum(ref def, _) = item.kind { - self.check(item.owner_id.def_id, item_visibility).generics().predicates(); + self.check_unnameable(item.owner_id.def_id, effective_vis); + + self.check(item.owner_id.def_id, item_visibility, effective_vis) + .generics() + .predicates(); for variant in def.variants { for field in variant.data.fields() { - self.check(field.def_id, item_visibility).ty(); + self.check(field.def_id, item_visibility, effective_vis).ty(); } } } @@ -1985,8 +2107,16 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { let item = tcx.hir().item(id); if let hir::ItemKind::ForeignMod { items, .. } = item.kind { for foreign_item in items { - let vis = tcx.local_visibility(foreign_item.id.owner_id.def_id); - self.check(foreign_item.id.owner_id.def_id, vis) + let foreign_item = tcx.hir().foreign_item(foreign_item.id); + + let ev = self.get(foreign_item.owner_id.def_id); + let vis = tcx.local_visibility(foreign_item.owner_id.def_id); + + if let ForeignItemKind::Type = foreign_item.kind { + self.check_unnameable(foreign_item.owner_id.def_id, ev); + } + + self.check(foreign_item.owner_id.def_id, vis, ev) .generics() .predicates() .ty(); @@ -1999,11 +2129,21 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { if let hir::ItemKind::Struct(ref struct_def, _) | hir::ItemKind::Union(ref struct_def, _) = item.kind { - self.check(item.owner_id.def_id, item_visibility).generics().predicates(); + self.check_unnameable(item.owner_id.def_id, effective_vis); + self.check(item.owner_id.def_id, item_visibility, effective_vis) + .generics() + .predicates(); for field in struct_def.fields() { let field_visibility = tcx.local_visibility(field.def_id); - self.check(field.def_id, min(item_visibility, field_visibility, tcx)).ty(); + let field_ev = self.get(field.def_id); + + self.check( + field.def_id, + min(item_visibility, field_visibility, tcx), + field_ev, + ) + .ty(); } } } @@ -2016,10 +2156,30 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { if let hir::ItemKind::Impl(ref impl_) = item.kind { let impl_vis = ty::Visibility::of_impl(item.owner_id.def_id, tcx, &Default::default()); + + // we are using the non-shallow version here, unlike when building the + // effective visisibilities table to avoid large number of false positives. + // For example: + // + // 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, + ); + // 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 if impl_.of_trait.is_none() { - self.check(item.owner_id.def_id, impl_vis).generics().predicates(); + self.check(item.owner_id.def_id, impl_vis, impl_ev).generics().predicates(); } for impl_item_ref in impl_.items { let impl_item_vis = if impl_.of_trait.is_none() { @@ -2031,10 +2191,18 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx> { } else { impl_vis }; + + let impl_item_ev = if impl_.of_trait.is_none() { + self.get(impl_item_ref.id.owner_id.def_id) + } else { + impl_ev + }; + self.check_assoc_item( impl_item_ref.id.owner_id.def_id, impl_item_ref.kind, impl_item_vis, + impl_item_ev, ); } } @@ -2186,7 +2354,11 @@ fn check_private_in_public(tcx: TyCtxt<'_>, (): ()) { } // Check for private types and traits in public interfaces. - let mut checker = PrivateItemsInPublicInterfacesChecker { tcx, old_error_set_ancestry }; + let mut checker = PrivateItemsInPublicInterfacesChecker { + tcx, + old_error_set_ancestry, + effective_visibilities, + }; for id in tcx.hir().items() { checker.check_item(id); diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs index 618250591ad..209d481d6f8 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs +++ b/compiler/rustc_target/src/spec/loongarch64_unknown_none.rs @@ -1,4 +1,4 @@ -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; +use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; use super::{Target, TargetOptions}; pub fn target() -> Target { @@ -13,8 +13,7 @@ pub fn target() -> Target { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No), llvm_abiname: "lp64d".into(), max_atomic_width: Some(64), - position_independent_executables: true, - static_position_independent_executables: true, + relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, code_model: Some(CodeModel::Small), ..Default::default() diff --git a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs index 23123d7630c..93df4221e61 100644 --- a/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs +++ b/compiler/rustc_target/src/spec/loongarch64_unknown_none_softfloat.rs @@ -1,4 +1,4 @@ -use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy}; +use super::{Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel}; use super::{Target, TargetOptions}; pub fn target() -> Target { @@ -14,8 +14,7 @@ pub fn target() -> Target { linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::No), llvm_abiname: "lp64s".into(), max_atomic_width: Some(64), - position_independent_executables: true, - static_position_independent_executables: true, + relocation_model: RelocModel::Static, panic_strategy: PanicStrategy::Abort, code_model: Some(CodeModel::Small), ..Default::default() diff --git a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs index f32ff0442a4..1b749b9c854 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly/mod.rs @@ -320,7 +320,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { candidates } - /// If the self type of a goal is a projection, computing the relevant candidates is difficult. + /// If the self type of a goal is an alias, computing the relevant candidates is difficult. /// /// To deal with this, we first try to normalize the self type and add the candidates for the normalized /// self type to the list of candidates in case that succeeds. We also have to consider candidates with the diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index e73d917a8ae..5783383e93e 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2663,9 +2663,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { | ObligationCauseCode::LetElse | ObligationCauseCode::BinOp { .. } | ObligationCauseCode::AscribeUserTypeProvePredicate(..) - | ObligationCauseCode::RustCall | ObligationCauseCode::DropImpl | ObligationCauseCode::ConstParam(_) => {} + ObligationCauseCode::RustCall => { + if let Some(pred) = predicate.to_opt_poly_trait_pred() + && Some(pred.def_id()) == self.tcx.lang_items().sized_trait() + { + err.note("argument required to be sized due to `extern \"rust-call\"` ABI"); + } + } ObligationCauseCode::SliceOrArrayElem => { err.note("slice and array elements must have `Sized` type"); } diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs index 2c089bb3149..66573b90db9 100644 --- a/library/alloc/src/collections/binary_heap/mod.rs +++ b/library/alloc/src/collections/binary_heap/mod.rs @@ -143,6 +143,7 @@ #![allow(missing_docs)] #![stable(feature = "rust1", since = "1.0.0")] +use core::alloc::Allocator; use core::fmt; use core::iter::{FusedIterator, InPlaceIterable, SourceIter, TrustedLen}; use core::mem::{self, swap, ManuallyDrop}; @@ -150,6 +151,7 @@ use core::num::NonZeroUsize; use core::ops::{Deref, DerefMut}; use core::ptr; +use crate::alloc::Global; use crate::collections::TryReserveError; use crate::slice; use crate::vec::{self, AsVecIntoIter, Vec}; @@ -271,8 +273,11 @@ mod tests; /// [peek\_mut]: BinaryHeap::peek_mut #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "BinaryHeap")] -pub struct BinaryHeap<T> { - data: Vec<T>, +pub struct BinaryHeap< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + data: Vec<T, A>, } /// Structure wrapping a mutable reference to the greatest item on a @@ -283,22 +288,26 @@ pub struct BinaryHeap<T> { /// /// [`peek_mut`]: BinaryHeap::peek_mut #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -pub struct PeekMut<'a, T: 'a + Ord> { - heap: &'a mut BinaryHeap<T>, +pub struct PeekMut< + 'a, + T: 'a + Ord, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + heap: &'a mut BinaryHeap<T, A>, // If a set_len + sift_down are required, this is Some. If a &mut T has not // yet been exposed to peek_mut()'s caller, it's None. original_len: Option<NonZeroUsize>, } #[stable(feature = "collection_debug", since = "1.17.0")] -impl<T: Ord + fmt::Debug> fmt::Debug for PeekMut<'_, T> { +impl<T: Ord + fmt::Debug, A: Allocator> fmt::Debug for PeekMut<'_, T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("PeekMut").field(&self.heap.data[0]).finish() } } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -impl<T: Ord> Drop for PeekMut<'_, T> { +impl<T: Ord, A: Allocator> Drop for PeekMut<'_, T, A> { fn drop(&mut self) { if let Some(original_len) = self.original_len { // SAFETY: That's how many elements were in the Vec at the time of @@ -315,7 +324,7 @@ impl<T: Ord> Drop for PeekMut<'_, T> { } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -impl<T: Ord> Deref for PeekMut<'_, T> { +impl<T: Ord, A: Allocator> Deref for PeekMut<'_, T, A> { type Target = T; fn deref(&self) -> &T { debug_assert!(!self.heap.is_empty()); @@ -325,7 +334,7 @@ impl<T: Ord> Deref for PeekMut<'_, T> { } #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] -impl<T: Ord> DerefMut for PeekMut<'_, T> { +impl<T: Ord, A: Allocator> DerefMut for PeekMut<'_, T, A> { fn deref_mut(&mut self) -> &mut T { debug_assert!(!self.heap.is_empty()); @@ -353,10 +362,10 @@ impl<T: Ord> DerefMut for PeekMut<'_, T> { } } -impl<'a, T: Ord> PeekMut<'a, T> { +impl<'a, T: Ord, A: Allocator> PeekMut<'a, T, A> { /// Removes the peeked value from the heap and returns it. #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")] - pub fn pop(mut this: PeekMut<'a, T>) -> T { + pub fn pop(mut this: PeekMut<'a, T, A>) -> T { if let Some(original_len) = this.original_len.take() { // SAFETY: This is how many elements were in the Vec at the time of // the BinaryHeap::peek_mut call. @@ -371,7 +380,7 @@ impl<'a, T: Ord> PeekMut<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Clone> Clone for BinaryHeap<T> { +impl<T: Clone, A: Allocator + Clone> Clone for BinaryHeap<T, A> { fn clone(&self) -> Self { BinaryHeap { data: self.data.clone() } } @@ -391,18 +400,22 @@ impl<T: Ord> Default for BinaryHeap<T> { } #[stable(feature = "binaryheap_debug", since = "1.4.0")] -impl<T: fmt::Debug> fmt::Debug for BinaryHeap<T> { +impl<T: fmt::Debug, A: Allocator> fmt::Debug for BinaryHeap<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() } } -struct RebuildOnDrop<'a, T: Ord> { - heap: &'a mut BinaryHeap<T>, +struct RebuildOnDrop< + 'a, + T: Ord, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + heap: &'a mut BinaryHeap<T, A>, rebuild_from: usize, } -impl<'a, T: Ord> Drop for RebuildOnDrop<'a, T> { +impl<T: Ord, A: Allocator> Drop for RebuildOnDrop<'_, T, A> { fn drop(&mut self) { self.heap.rebuild_tail(self.rebuild_from); } @@ -446,6 +459,52 @@ impl<T: Ord> BinaryHeap<T> { pub fn with_capacity(capacity: usize) -> BinaryHeap<T> { BinaryHeap { data: Vec::with_capacity(capacity) } } +} + +impl<T: Ord, A: Allocator> BinaryHeap<T, A> { + /// Creates an empty `BinaryHeap` as a max-heap, using `A` as allocator. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::new_in(System); + /// heap.push(4); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub fn new_in(alloc: A) -> BinaryHeap<T, A> { + BinaryHeap { data: Vec::new_in(alloc) } + } + + /// Creates an empty `BinaryHeap` with at least the specified capacity, using `A` as allocator. + /// + /// The binary heap will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the binary heap will not allocate. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::alloc::System; + /// use std::collections::BinaryHeap; + /// let mut heap = BinaryHeap::with_capacity_in(10, System); + /// heap.push(4); + /// ``` + #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub fn with_capacity_in(capacity: usize, alloc: A) -> BinaryHeap<T, A> { + BinaryHeap { data: Vec::with_capacity_in(capacity, alloc) } + } /// Returns a mutable reference to the greatest item in the binary heap, or /// `None` if it is empty. @@ -478,7 +537,7 @@ impl<T: Ord> BinaryHeap<T> { /// If the item is modified then the worst case time complexity is *O*(log(*n*)), /// otherwise it's *O*(1). #[stable(feature = "binary_heap_peek_mut", since = "1.12.0")] - pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T>> { + pub fn peek_mut(&mut self) -> Option<PeekMut<'_, T, A>> { if self.is_empty() { None } else { Some(PeekMut { heap: self, original_len: None }) } } @@ -573,7 +632,7 @@ impl<T: Ord> BinaryHeap<T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] - pub fn into_sorted_vec(mut self) -> Vec<T> { + pub fn into_sorted_vec(mut self) -> Vec<T, A> { let mut end = self.len(); while end > 1 { end -= 1; @@ -831,7 +890,7 @@ impl<T: Ord> BinaryHeap<T> { /// ``` #[inline] #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] - pub fn drain_sorted(&mut self) -> DrainSorted<'_, T> { + pub fn drain_sorted(&mut self) -> DrainSorted<'_, T, A> { DrainSorted { inner: self } } @@ -874,7 +933,7 @@ impl<T: Ord> BinaryHeap<T> { } } -impl<T> BinaryHeap<T> { +impl<T, A: Allocator> BinaryHeap<T, A> { /// Returns an iterator visiting all values in the underlying vector, in /// arbitrary order. /// @@ -911,7 +970,7 @@ impl<T> BinaryHeap<T> { /// assert_eq!(heap.into_iter_sorted().take(2).collect::<Vec<_>>(), [5, 4]); /// ``` #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] - pub fn into_iter_sorted(self) -> IntoIterSorted<T> { + pub fn into_iter_sorted(self) -> IntoIterSorted<T, A> { IntoIterSorted { inner: self } } @@ -1178,10 +1237,17 @@ impl<T> BinaryHeap<T> { /// ``` #[must_use = "`self` will be dropped if the result is not used"] #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] - pub fn into_vec(self) -> Vec<T> { + pub fn into_vec(self) -> Vec<T, A> { self.into() } + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + #[inline] + pub fn allocator(&self) -> &A { + self.data.allocator() + } + /// Returns the length of the binary heap. /// /// # Examples @@ -1249,7 +1315,7 @@ impl<T> BinaryHeap<T> { /// ``` #[inline] #[stable(feature = "drain", since = "1.6.0")] - pub fn drain(&mut self) -> Drain<'_, T> { + pub fn drain(&mut self) -> Drain<'_, T, A> { Drain { iter: self.data.drain(..) } } @@ -1419,19 +1485,30 @@ impl<T> FusedIterator for Iter<'_, T> {} /// [`into_iter`]: BinaryHeap::into_iter #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] -pub struct IntoIter<T> { - iter: vec::IntoIter<T>, +pub struct IntoIter< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + iter: vec::IntoIter<T, A>, +} + +impl<T, A: Allocator> IntoIter<T, A> { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.iter.allocator() + } } #[stable(feature = "collection_debug", since = "1.17.0")] -impl<T: fmt::Debug> fmt::Debug for IntoIter<T> { +impl<T: fmt::Debug, A: Allocator> fmt::Debug for IntoIter<T, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("IntoIter").field(&self.iter.as_slice()).finish() } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> Iterator for IntoIter<T> { +impl<T, A: Allocator> Iterator for IntoIter<T, A> { type Item = T; #[inline] @@ -1446,7 +1523,7 @@ impl<T> Iterator for IntoIter<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> DoubleEndedIterator for IntoIter<T> { +impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> { #[inline] fn next_back(&mut self) -> Option<T> { self.iter.next_back() @@ -1454,14 +1531,14 @@ impl<T> DoubleEndedIterator for IntoIter<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> ExactSizeIterator for IntoIter<T> { +impl<T, A: Allocator> ExactSizeIterator for IntoIter<T, A> { fn is_empty(&self) -> bool { self.iter.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] -impl<T> FusedIterator for IntoIter<T> {} +impl<T, A: Allocator> FusedIterator for IntoIter<T, A> {} #[stable(feature = "default_iters", since = "1.70.0")] impl<T> Default for IntoIter<T> { @@ -1481,8 +1558,8 @@ impl<T> Default for IntoIter<T> { // also refer to the vec::in_place_collect module documentation to get an overview #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] -unsafe impl<T> SourceIter for IntoIter<T> { - type Source = IntoIter<T>; +unsafe impl<T, A: Allocator> SourceIter for IntoIter<T, A> { + type Source = IntoIter<T, A>; #[inline] unsafe fn as_inner(&mut self) -> &mut Self::Source { @@ -1492,7 +1569,7 @@ unsafe impl<T> SourceIter for IntoIter<T> { #[unstable(issue = "none", feature = "inplace_iteration")] #[doc(hidden)] -unsafe impl<I> InPlaceIterable for IntoIter<I> {} +unsafe impl<I, A: Allocator> InPlaceIterable for IntoIter<I, A> {} unsafe impl<I> AsVecIntoIter for IntoIter<I> { type Item = I; @@ -1505,12 +1582,23 @@ unsafe impl<I> AsVecIntoIter for IntoIter<I> { #[must_use = "iterators are lazy and do nothing unless consumed"] #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] #[derive(Clone, Debug)] -pub struct IntoIterSorted<T> { - inner: BinaryHeap<T>, +pub struct IntoIterSorted< + T, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + inner: BinaryHeap<T, A>, +} + +impl<T, A: Allocator> IntoIterSorted<T, A> { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.inner.allocator() + } } #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] -impl<T: Ord> Iterator for IntoIterSorted<T> { +impl<T: Ord, A: Allocator> Iterator for IntoIterSorted<T, A> { type Item = T; #[inline] @@ -1526,13 +1614,13 @@ impl<T: Ord> Iterator for IntoIterSorted<T> { } #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] -impl<T: Ord> ExactSizeIterator for IntoIterSorted<T> {} +impl<T: Ord, A: Allocator> ExactSizeIterator for IntoIterSorted<T, A> {} #[unstable(feature = "binary_heap_into_iter_sorted", issue = "59278")] -impl<T: Ord> FusedIterator for IntoIterSorted<T> {} +impl<T: Ord, A: Allocator> FusedIterator for IntoIterSorted<T, A> {} #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<T: Ord> TrustedLen for IntoIterSorted<T> {} +unsafe impl<T: Ord, A: Allocator> TrustedLen for IntoIterSorted<T, A> {} /// A draining iterator over the elements of a `BinaryHeap`. /// @@ -1542,12 +1630,24 @@ unsafe impl<T: Ord> TrustedLen for IntoIterSorted<T> {} /// [`drain`]: BinaryHeap::drain #[stable(feature = "drain", since = "1.6.0")] #[derive(Debug)] -pub struct Drain<'a, T: 'a> { - iter: vec::Drain<'a, T>, +pub struct Drain< + 'a, + T: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + iter: vec::Drain<'a, T, A>, +} + +impl<T, A: Allocator> Drain<'_, T, A> { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.iter.allocator() + } } #[stable(feature = "drain", since = "1.6.0")] -impl<T> Iterator for Drain<'_, T> { +impl<T, A: Allocator> Iterator for Drain<'_, T, A> { type Item = T; #[inline] @@ -1562,7 +1662,7 @@ impl<T> Iterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl<T> DoubleEndedIterator for Drain<'_, T> { +impl<T, A: Allocator> DoubleEndedIterator for Drain<'_, T, A> { #[inline] fn next_back(&mut self) -> Option<T> { self.iter.next_back() @@ -1570,14 +1670,14 @@ impl<T> DoubleEndedIterator for Drain<'_, T> { } #[stable(feature = "drain", since = "1.6.0")] -impl<T> ExactSizeIterator for Drain<'_, T> { +impl<T, A: Allocator> ExactSizeIterator for Drain<'_, T, A> { fn is_empty(&self) -> bool { self.iter.is_empty() } } #[stable(feature = "fused", since = "1.26.0")] -impl<T> FusedIterator for Drain<'_, T> {} +impl<T, A: Allocator> FusedIterator for Drain<'_, T, A> {} /// A draining iterator over the elements of a `BinaryHeap`. /// @@ -1587,17 +1687,29 @@ impl<T> FusedIterator for Drain<'_, T> {} /// [`drain_sorted`]: BinaryHeap::drain_sorted #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] #[derive(Debug)] -pub struct DrainSorted<'a, T: Ord> { - inner: &'a mut BinaryHeap<T>, +pub struct DrainSorted< + 'a, + T: Ord, + #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, +> { + inner: &'a mut BinaryHeap<T, A>, +} + +impl<'a, T: Ord, A: Allocator> DrainSorted<'a, T, A> { + /// Returns a reference to the underlying allocator. + #[unstable(feature = "allocator_api", issue = "32838")] + pub fn allocator(&self) -> &A { + self.inner.allocator() + } } #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl<'a, T: Ord> Drop for DrainSorted<'a, T> { +impl<'a, T: Ord, A: Allocator> Drop for DrainSorted<'a, T, A> { /// Removes heap elements in heap order. fn drop(&mut self) { - struct DropGuard<'r, 'a, T: Ord>(&'r mut DrainSorted<'a, T>); + struct DropGuard<'r, 'a, T: Ord, A: Allocator>(&'r mut DrainSorted<'a, T, A>); - impl<'r, 'a, T: Ord> Drop for DropGuard<'r, 'a, T> { + impl<'r, 'a, T: Ord, A: Allocator> Drop for DropGuard<'r, 'a, T, A> { fn drop(&mut self) { while self.0.inner.pop().is_some() {} } @@ -1612,7 +1724,7 @@ impl<'a, T: Ord> Drop for DrainSorted<'a, T> { } #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl<T: Ord> Iterator for DrainSorted<'_, T> { +impl<T: Ord, A: Allocator> Iterator for DrainSorted<'_, T, A> { type Item = T; #[inline] @@ -1628,20 +1740,20 @@ impl<T: Ord> Iterator for DrainSorted<'_, T> { } #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl<T: Ord> ExactSizeIterator for DrainSorted<'_, T> {} +impl<T: Ord, A: Allocator> ExactSizeIterator for DrainSorted<'_, T, A> {} #[unstable(feature = "binary_heap_drain_sorted", issue = "59278")] -impl<T: Ord> FusedIterator for DrainSorted<'_, T> {} +impl<T: Ord, A: Allocator> FusedIterator for DrainSorted<'_, T, A> {} #[unstable(feature = "trusted_len", issue = "37572")] -unsafe impl<T: Ord> TrustedLen for DrainSorted<'_, T> {} +unsafe impl<T: Ord, A: Allocator> TrustedLen for DrainSorted<'_, T, A> {} #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] -impl<T: Ord> From<Vec<T>> for BinaryHeap<T> { +impl<T: Ord, A: Allocator> From<Vec<T, A>> for BinaryHeap<T, A> { /// Converts a `Vec<T>` into a `BinaryHeap<T>`. /// /// This conversion happens in-place, and has *O*(*n*) time complexity. - fn from(vec: Vec<T>) -> BinaryHeap<T> { + fn from(vec: Vec<T, A>) -> BinaryHeap<T, A> { let mut heap = BinaryHeap { data: vec }; heap.rebuild(); heap @@ -1665,12 +1777,12 @@ impl<T: Ord, const N: usize> From<[T; N]> for BinaryHeap<T> { } #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] -impl<T> From<BinaryHeap<T>> for Vec<T> { +impl<T, A: Allocator> From<BinaryHeap<T, A>> for Vec<T, A> { /// Converts a `BinaryHeap<T>` into a `Vec<T>`. /// /// This conversion requires no data movement or allocation, and has /// constant time complexity. - fn from(heap: BinaryHeap<T>) -> Vec<T> { + fn from(heap: BinaryHeap<T, A>) -> Vec<T, A> { heap.data } } @@ -1683,9 +1795,9 @@ impl<T: Ord> FromIterator<T> for BinaryHeap<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> IntoIterator for BinaryHeap<T> { +impl<T, A: Allocator> IntoIterator for BinaryHeap<T, A> { type Item = T; - type IntoIter = IntoIter<T>; + type IntoIter = IntoIter<T, A>; /// Creates a consuming iterator, that is, one that moves each value out of /// the binary heap in arbitrary order. The binary heap cannot be used @@ -1705,13 +1817,13 @@ impl<T> IntoIterator for BinaryHeap<T> { /// println!("{x}"); /// } /// ``` - fn into_iter(self) -> IntoIter<T> { + fn into_iter(self) -> IntoIter<T, A> { IntoIter { iter: self.data.into_iter() } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a BinaryHeap<T> { +impl<'a, T, A: Allocator> IntoIterator for &'a BinaryHeap<T, A> { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1721,7 +1833,7 @@ impl<'a, T> IntoIterator for &'a BinaryHeap<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Ord> Extend<T> for BinaryHeap<T> { +impl<T: Ord, A: Allocator> Extend<T> for BinaryHeap<T, A> { #[inline] fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { let guard = RebuildOnDrop { rebuild_from: self.len(), heap: self }; @@ -1740,7 +1852,7 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> { } #[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> { +impl<'a, T: 'a + Ord + Copy, A: Allocator> Extend<&'a T> for BinaryHeap<T, A> { fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index e753647ff78..c6f43857887 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -106,7 +106,7 @@ impl<T: ?Sized> *mut T { /// with [`cast_mut`] on `*const T` and may have documentation value if used instead of implicit /// coercion. /// - /// [`cast_mut`]: pointer::cast_mut + /// [`cast_mut`]: #method.cast_mut #[stable(feature = "ptr_const_cast", since = "1.65.0")] #[rustc_const_stable(feature = "ptr_const_cast", since = "1.65.0")] #[inline(always)] @@ -117,7 +117,7 @@ impl<T: ?Sized> *mut T { /// Casts a pointer to its raw bits. /// /// This is equivalent to `as usize`, but is more specific to enhance readability. - /// The inverse method is [`from_bits`](pointer#method.from_bits-1). + /// The inverse method is [`from_bits`](#method.from_bits-1). /// /// In particular, `*p as usize` and `p as usize` will both compile for /// pointers to numeric types but do very different things, so using this @@ -153,7 +153,7 @@ impl<T: ?Sized> *mut T { /// Creates a pointer from its raw bits. /// /// This is equivalent to `as *mut T`, but is more specific to enhance readability. - /// The inverse method is [`to_bits`](pointer#method.to_bits-1). + /// The inverse method is [`to_bits`](#method.to_bits-1). /// /// # Examples /// @@ -303,7 +303,7 @@ impl<T: ?Sized> *mut T { /// /// For the mutable counterpart see [`as_mut`]. /// - /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 + /// [`as_uninit_ref`]: #method.as_uninit_ref-1 /// [`as_mut`]: #method.as_mut /// /// # Safety @@ -369,7 +369,7 @@ impl<T: ?Sized> *mut T { /// /// For the mutable counterpart see [`as_uninit_mut`]. /// - /// [`as_ref`]: pointer#method.as_ref-1 + /// [`as_ref`]: #method.as_ref-1 /// [`as_uninit_mut`]: #method.as_uninit_mut /// /// # Safety @@ -624,7 +624,7 @@ impl<T: ?Sized> *mut T { /// For the shared counterpart see [`as_ref`]. /// /// [`as_uninit_mut`]: #method.as_uninit_mut - /// [`as_ref`]: pointer#method.as_ref-1 + /// [`as_ref`]: #method.as_ref-1 /// /// # Safety /// @@ -689,7 +689,7 @@ impl<T: ?Sized> *mut T { /// For the shared counterpart see [`as_uninit_ref`]. /// /// [`as_mut`]: #method.as_mut - /// [`as_uninit_ref`]: pointer#method.as_uninit_ref-1 + /// [`as_uninit_ref`]: #method.as_uninit_ref-1 /// /// # Safety /// @@ -779,7 +779,7 @@ impl<T: ?Sized> *mut T { /// /// This function is the inverse of [`offset`]. /// - /// [`offset`]: pointer#method.offset-1 + /// [`offset`]: #method.offset-1 /// /// # Safety /// @@ -2051,7 +2051,7 @@ impl<T> *mut [T] { /// /// For the mutable counterpart see [`as_uninit_slice_mut`]. /// - /// [`as_ref`]: pointer#method.as_ref-1 + /// [`as_ref`]: #method.as_ref-1 /// [`as_uninit_slice_mut`]: #method.as_uninit_slice_mut /// /// # Safety diff --git a/library/std/src/sys/windows/c/windows_sys.rs b/library/std/src/sys/windows/c/windows_sys.rs index 8c8b006a1d3..a4294f336fe 100644 --- a/library/std/src/sys/windows/c/windows_sys.rs +++ b/library/std/src/sys/windows/c/windows_sys.rs @@ -4275,3 +4275,23 @@ impl ::core::clone::Clone for XSAVE_FORMAT { *self } } +// Begin of ARM32 shim +// The raw content of this file should be processed by `generate-windows-sys` +// to be merged with the generated binding. It is not supposed to be used as +// a normal Rust module. +cfg_if::cfg_if! { +if #[cfg(target_arch = "arm")] { +#[repr(C)] +pub struct WSADATA { + pub wVersion: u16, + pub wHighVersion: u16, + pub szDescription: [u8; 257], + pub szSystemStatus: [u8; 129], + pub iMaxSockets: u16, + pub iMaxUdpDg: u16, + pub lpVendorInfo: PSTR, +} +pub enum CONTEXT {} +} +} +// End of ARM32 shim diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index d9973185bc4..1230bb5deed 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -195,7 +195,7 @@ mod local; cfg_if::cfg_if! { if #[cfg(test)] { - // Avoid duplicating the global state assoicated with thread-locals between this crate and + // Avoid duplicating the global state associated with thread-locals between this crate and // realstd. Miri relies on this. pub use realstd::thread::{local_impl, AccessError, LocalKey}; } else { diff --git a/src/bootstrap/render_tests.rs b/src/bootstrap/render_tests.rs index 06ab820953d..98a468c883d 100644 --- a/src/bootstrap/render_tests.rs +++ b/src/bootstrap/render_tests.rs @@ -7,7 +7,7 @@ //! to reimplement all the rendering logic in this module because of that. use crate::builder::Builder; -use std::io::{BufRead, BufReader, Write}; +use std::io::{BufRead, BufReader, Read, Write}; use std::process::{ChildStdout, Command, Stdio}; use std::time::Duration; use termcolor::{Color, ColorSpec, WriteColor}; @@ -20,15 +20,15 @@ pub(crate) fn add_flags_and_try_run_tests(builder: &Builder<'_>, cmd: &mut Comma } cmd.args(&["-Z", "unstable-options", "--format", "json"]); - try_run_tests(builder, cmd) + try_run_tests(builder, cmd, false) } -pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool { +pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { if builder.config.dry_run() { return true; } - if !run_tests(builder, cmd) { + if !run_tests(builder, cmd, stream) { if builder.fail_fast { crate::detail_exit_macro!(1); } else { @@ -41,7 +41,7 @@ pub(crate) fn try_run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool { } } -fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool { +fn run_tests(builder: &Builder<'_>, cmd: &mut Command, stream: bool) -> bool { cmd.stdout(Stdio::piped()); builder.verbose(&format!("running: {cmd:?}")); @@ -50,7 +50,12 @@ fn run_tests(builder: &Builder<'_>, cmd: &mut Command) -> bool { // This runs until the stdout of the child is closed, which means the child exited. We don't // run this on another thread since the builder is not Sync. - Renderer::new(process.stdout.take().unwrap(), builder).render_all(); + let renderer = Renderer::new(process.stdout.take().unwrap(), builder); + if stream { + renderer.stream_all(); + } else { + renderer.render_all(); + } let result = process.wait_with_output().unwrap(); if !result.status.success() && builder.is_verbose() { @@ -112,6 +117,23 @@ impl<'a> Renderer<'a> { } } + /// Renders the stdout characters one by one + fn stream_all(mut self) { + let mut buffer = [0; 1]; + loop { + match self.stdout.read(&mut buffer) { + Ok(0) => break, + Ok(_) => { + let mut stdout = std::io::stdout(); + stdout.write_all(&buffer).unwrap(); + let _ = stdout.flush(); + } + Err(err) if err.kind() == std::io::ErrorKind::UnexpectedEof => break, + Err(err) => panic!("failed to read output of test runner: {err}"), + } + } + } + fn render_test_outcome(&mut self, outcome: Outcome<'_>, test: &TestOutcome) { self.executed_tests += 1; diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index f31ba946099..cde77f4720b 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1035,7 +1035,7 @@ impl Step for RustdocGUI { } let _time = util::timeit(&builder); - crate::render_tests::try_run_tests(builder, &mut cmd); + crate::render_tests::try_run_tests(builder, &mut cmd, true); } } @@ -1732,7 +1732,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the suite, mode, &compiler.host, target )); let _time = util::timeit(&builder); - crate::render_tests::try_run_tests(builder, &mut cmd); + crate::render_tests::try_run_tests(builder, &mut cmd, false); if let Some(compare_mode) = compare_mode { cmd.arg("--compare-mode").arg(compare_mode); @@ -1755,7 +1755,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the suite, mode, compare_mode, &compiler.host, target )); let _time = util::timeit(&builder); - crate::render_tests::try_run_tests(builder, &mut cmd); + crate::render_tests::try_run_tests(builder, &mut cmd, false); } } } diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index baffee0964d..f205ff15ec3 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -53,15 +53,12 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::Mutability; -use rustc_infer::infer::TyCtxtInferExt; -use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::middle::stability; -use rustc_middle::ty::{ParamEnv, TyCtxt}; +use rustc_middle::ty::TyCtxt; use rustc_span::{ symbol::{sym, Symbol}, BytePos, FileName, RealFileName, }; -use rustc_trait_selection::traits::ObligationCtxt; use serde::ser::{SerializeMap, SerializeSeq}; use serde::{Serialize, Serializer}; @@ -1115,47 +1112,15 @@ fn render_assoc_items<'a, 'cx: 'a>( containing_item: &'a clean::Item, it: DefId, what: AssocItemRender<'a>, - aliased_type: Option<DefId>, ) -> impl fmt::Display + 'a + Captures<'cx> { let mut derefs = DefIdSet::default(); derefs.insert(it); display_fn(move |f| { - render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs, aliased_type); + render_assoc_items_inner(f, cx, containing_item, it, what, &mut derefs); Ok(()) }) } -/// Check whether `impl_def_id` may apply to *some instantiation* of `item_def_id`. -fn is_valid_impl_for(tcx: TyCtxt<'_>, item_def_id: DefId, impl_def_id: DefId) -> bool { - let infcx = tcx.infer_ctxt().intercrate(true).build(); - let ocx = ObligationCtxt::new(&infcx); - let param_env = ParamEnv::empty(); - - let alias_substs = infcx.fresh_substs_for_item(rustc_span::DUMMY_SP, item_def_id); - let alias_ty = tcx.type_of(item_def_id).subst(tcx, alias_substs); - let alias_bounds = tcx.predicates_of(item_def_id).instantiate(tcx, alias_substs); - - let impl_substs = infcx.fresh_substs_for_item(rustc_span::DUMMY_SP, impl_def_id); - let impl_self_ty = tcx.type_of(impl_def_id).subst(tcx, impl_substs); - let impl_bounds = tcx.predicates_of(impl_def_id).instantiate(tcx, impl_substs); - - if ocx.eq(&ObligationCause::dummy(), param_env, impl_self_ty, alias_ty).is_err() { - return false; - } - ocx.register_obligations( - alias_bounds - .iter() - .chain(impl_bounds) - .map(|(p, _)| Obligation::new(tcx, ObligationCause::dummy(), param_env, p)), - ); - - let errors = ocx.select_where_possible(); - errors.is_empty() -} - -// If `aliased_type` is `Some`, it means `it` is a type alias and `aliased_type` is the "actual" -// type aliased behind `it`. It is used to check whether or not the implementation of the aliased -// type can be displayed on the alias doc page. fn render_assoc_items_inner( mut w: &mut dyn fmt::Write, cx: &mut Context<'_>, @@ -1163,28 +1128,12 @@ fn render_assoc_items_inner( it: DefId, what: AssocItemRender<'_>, derefs: &mut DefIdSet, - aliased_type: Option<DefId>, ) { info!("Documenting associated items of {:?}", containing_item.name); let shared = Rc::clone(&cx.shared); let cache = &shared.cache; - let empty = Vec::new(); - let v = match cache.impls.get(&it) { - Some(v) => v, - None => &empty, - }; - let v2 = match aliased_type { - Some(aliased_type) => cache.impls.get(&aliased_type).unwrap_or(&empty), - None => &empty, - }; - if v.is_empty() && v2.is_empty() { - return; - } - let mut saw_impls = FxHashSet::default(); - let (non_trait, traits): (Vec<_>, _) = - v.iter().chain(v2).partition(|i| i.inner_impl().trait_.is_none()); - let tcx = cx.tcx(); - let is_alias = aliased_type.is_some(); + let Some(v) = cache.impls.get(&it) else { return }; + let (non_trait, traits): (Vec<_>, _) = v.iter().partition(|i| i.inner_impl().trait_.is_none()); if !non_trait.is_empty() { let mut tmp_buf = Buffer::html(); let (render_mode, id, class_html) = match what { @@ -1216,12 +1165,6 @@ fn render_assoc_items_inner( }; let mut impls_buf = Buffer::html(); for i in &non_trait { - if !saw_impls.insert(i.def_id()) { - continue; - } - if is_alias && !is_valid_impl_for(tcx, it, i.def_id()) { - continue; - } render_impl( &mut impls_buf, cx, @@ -1250,14 +1193,9 @@ fn render_assoc_items_inner( if !traits.is_empty() { let deref_impl = traits.iter().find(|t| t.trait_did() == cx.tcx().lang_items().deref_trait()); - if let Some(impl_) = deref_impl && - (!is_alias || is_valid_impl_for(tcx, it, impl_.def_id())) - { + if let Some(impl_) = deref_impl { let has_deref_mut = - traits.iter().any(|t| { - t.trait_did() == cx.tcx().lang_items().deref_mut_trait() && - (!is_alias || is_valid_impl_for(tcx, it, t.def_id())) - }); + traits.iter().any(|t| t.trait_did() == cx.tcx().lang_items().deref_mut_trait()); render_deref_methods(&mut w, cx, impl_, containing_item, has_deref_mut, derefs); } @@ -1267,14 +1205,10 @@ fn render_assoc_items_inner( return; } - let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = traits - .into_iter() - .filter(|t| saw_impls.insert(t.def_id())) - .partition(|t| t.inner_impl().kind.is_auto()); - let (blanket_impl, concrete): (Vec<&Impl>, _) = concrete - .into_iter() - .filter(|t| !is_alias || is_valid_impl_for(tcx, it, t.def_id())) - .partition(|t| t.inner_impl().kind.is_blanket()); + let (synthetic, concrete): (Vec<&Impl>, Vec<&Impl>) = + traits.into_iter().partition(|t| t.inner_impl().kind.is_auto()); + let (blanket_impl, concrete): (Vec<&Impl>, _) = + concrete.into_iter().partition(|t| t.inner_impl().kind.is_blanket()); render_all_impls(w, cx, containing_item, &concrete, &synthetic, &blanket_impl); } @@ -1313,10 +1247,10 @@ fn render_deref_methods( return; } } - render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs, None); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } else if let Some(prim) = target.primitive_type() { if let Some(&did) = cache.primitive_locations.get(&prim) { - render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs, None); + render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs); } } } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 02cfad6b346..383e3c17088 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -129,7 +129,7 @@ macro_rules! item_template_methods { display_fn(move |f| { let (item, mut cx) = self.item_and_mut_cx(); let def_id = item.item_id.expect_def_id(); - let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All, None); + let v = render_assoc_items(*cx, item, def_id, AssocItemRender::All); write!(f, "{v}") }) } @@ -953,11 +953,7 @@ fn item_trait(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean: } // If there are methods directly on this trait object, render them here. - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)); let cloned_shared = Rc::clone(&cx.shared); let cache = &cloned_shared.cache; @@ -1189,12 +1185,8 @@ fn item_trait_alias( // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ) - .unwrap(); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) + .unwrap(); } fn item_opaque_ty( @@ -1222,12 +1214,8 @@ fn item_opaque_ty( // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but // we need #14072 to make sense of the generics. - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ) - .unwrap(); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) + .unwrap(); } fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clean::Typedef) { @@ -1251,11 +1239,11 @@ fn item_typedef(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, t: &clea write!(w, "{}", document(cx, it, None, HeadingOffset::H2)); let def_id = it.item_id.expect_def_id(); - write!( - w, - "{}", - render_assoc_items(cx, it, def_id, AssocItemRender::All, t.type_.def_id(&cx.cache())) - ); + // Render any items associated directly to this alias, as otherwise they + // won't be visible anywhere in the docs. It would be nice to also show + // associated items from the aliased type (see discussion in #32077), but + // we need #14072 to make sense of the generics. + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); write!(w, "{}", document_type_layout(cx, def_id)); } @@ -1494,7 +1482,7 @@ fn item_enum(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, e: &clean:: write!(w, "</div>"); } let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All, None)); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); write!(w, "{}", document_type_layout(cx, def_id)); } @@ -1537,7 +1525,7 @@ fn item_primitive(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean::Ite let def_id = it.item_id.expect_def_id(); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); if it.name.map(|n| n.as_str() != "reference").unwrap_or(false) { - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All, None)).unwrap(); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)).unwrap(); } else { // We handle the "reference" primitive type on its own because we only want to list // implementations on generic types. @@ -1642,7 +1630,7 @@ fn item_struct(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, s: &clean } } let def_id = it.item_id.expect_def_id(); - write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All, None)); + write!(w, "{}", render_assoc_items(cx, it, def_id, AssocItemRender::All)); write!(w, "{}", document_type_layout(cx, def_id)); } @@ -1677,12 +1665,8 @@ fn item_foreign_type(w: &mut impl fmt::Write, cx: &mut Context<'_>, it: &clean:: }); write!(w, "{}", document(cx, it, None, HeadingOffset::H2)).unwrap(); - write!( - w, - "{}", - render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All, None) - ) - .unwrap(); + write!(w, "{}", render_assoc_items(cx, it, it.item_id.expect_def_id(), AssocItemRender::All)) + .unwrap(); } fn item_keyword(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item) { diff --git a/src/tools/generate-windows-sys/src/arm_shim.rs b/src/tools/generate-windows-sys/src/arm_shim.rs new file mode 100644 index 00000000000..17c2ccb223c --- /dev/null +++ b/src/tools/generate-windows-sys/src/arm_shim.rs @@ -0,0 +1,20 @@ +// Begin of ARM32 shim +// The raw content of this file should be processed by `generate-windows-sys` +// to be merged with the generated binding. It is not supposed to be used as +// a normal Rust module. +cfg_if::cfg_if! { +if #[cfg(target_arch = "arm")] { +#[repr(C)] +pub struct WSADATA { + pub wVersion: u16, + pub wHighVersion: u16, + pub szDescription: [u8; 257], + pub szSystemStatus: [u8; 129], + pub iMaxSockets: u16, + pub iMaxUdpDg: u16, + pub lpVendorInfo: PSTR, +} +pub enum CONTEXT {} +} +} +// End of ARM32 shim diff --git a/src/tools/generate-windows-sys/src/main.rs b/src/tools/generate-windows-sys/src/main.rs index 91d981462e8..65e480715ee 100644 --- a/src/tools/generate-windows-sys/src/main.rs +++ b/src/tools/generate-windows-sys/src/main.rs @@ -11,6 +11,9 @@ const PRELUDE: &str = r#"// This file is autogenerated. // ignore-tidy-filelength "#; +/// This is a shim for the ARM (32-bit) architecture, which is no longer supported by windows-rs. +const ARM_SHIM: &str = include_str!("arm_shim.rs"); + fn main() -> io::Result<()> { let mut path: PathBuf = std::env::args_os().nth(1).expect("a path to the rust repository is required").into(); @@ -32,6 +35,7 @@ fn main() -> io::Result<()> { let mut f = std::fs::File::create(&path)?; f.write_all(PRELUDE.as_bytes())?; f.write_all(bindings.as_bytes())?; + f.write_all(ARM_SHIM.as_bytes())?; Ok(()) } diff --git a/tests/rustdoc-gui/headers-color.goml b/tests/rustdoc-gui/headers-color.goml index 7d83833a8bd..a7ac94c4943 100644 --- a/tests/rustdoc-gui/headers-color.goml +++ b/tests/rustdoc-gui/headers-color.goml @@ -42,29 +42,29 @@ call-function: ( "check-colors", { "theme": "ayu", - "color": "rgb(197, 197, 197)", - "code_header_color": "rgb(230, 225, 207)", + "color": "#c5c5c5", + "code_header_color": "#e6e1cf", "focus_background_color": "rgba(255, 236, 164, 0.06)", - "headings_color": "rgb(57, 175, 215)", + "headings_color": "#39afd7", }, ) call-function: ( "check-colors", { "theme": "dark", - "color": "rgb(221, 221, 221)", - "code_header_color": "rgb(221, 221, 221)", - "focus_background_color": "rgb(73, 74, 61)", - "headings_color": "rgb(210, 153, 29)", + "color": "#ddd", + "code_header_color": "#ddd", + "focus_background_color": "#494a3d", + "headings_color": "#d2991d", }, ) call-function: ( "check-colors", { "theme": "light", - "color": "rgb(0, 0, 0)", - "code_header_color": "rgb(0, 0, 0)", - "focus_background_color": "rgb(253, 255, 211)", - "headings_color": "rgb(56, 115, 173)", + "color": "black", + "code_header_color": "black", + "focus_background_color": "#fdffd3", + "headings_color": "#3873ad", }, ) diff --git a/tests/rustdoc/issue-112515-impl-ty-alias.rs b/tests/rustdoc/issue-112515-impl-ty-alias.rs new file mode 100644 index 00000000000..161188ee576 --- /dev/null +++ b/tests/rustdoc/issue-112515-impl-ty-alias.rs @@ -0,0 +1,30 @@ +// Regression test for <https://github.com/rust-lang/rust/issues/112515>. +// It's to ensure that this code doesn't have infinite loop in rustdoc when +// trying to retrive type alias implementations. + +// ignore-tidy-linelength + +pub type Boom = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<u64, u8>, ()>, ()>, ()>, u8>, ()>, u8>, ()>, u8>, u8>, ()>, ()>, ()>, u8>, u8>, u8>, ()>, ()>, u8>, ()>, ()>, ()>, u8>, u8>, ()>, ()>, ()>, ()>, ()>, u8>, ()>, ()>, u8>, ()>, ()>, ()>, u8>, ()>, ()>, u8>, u8>, u8>, u8>, ()>, u8>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>, ()>; +pub struct S<T, U>(T, U); + +pub trait A {} + +pub trait B<T> { + type P; +} + +impl A for u64 {} + +impl<T, U> A for S<T, U> {} + +impl<T> B<u8> for S<T, ()> +where + T: B<u8>, + <T as B<u8>>::P: A, +{ + type P = (); +} + +impl<T: A, U, V> B<T> for S<U, V> { + type P = (); +} diff --git a/tests/rustdoc/issue-32077-type-alias-impls.rs b/tests/rustdoc/issue-32077-type-alias-impls.rs deleted file mode 100644 index 555d0579bee..00000000000 --- a/tests/rustdoc/issue-32077-type-alias-impls.rs +++ /dev/null @@ -1,59 +0,0 @@ -// Regression test for <https://github.com/rust-lang/rust/issues/32077>. - -#![crate_name = "foo"] - -pub struct GenericStruct<T>(T); - -impl<T> GenericStruct<T> { - pub fn on_gen(arg: T) {} -} - -impl GenericStruct<u32> { - pub fn on_u32(arg: u32) {} -} - -pub trait Foo {} -pub trait Bar {} - -impl<T> Foo for GenericStruct<T> {} -impl Bar for GenericStruct<u32> {} - -// @has 'foo/type.TypedefStruct.html' -// We check that we have the implementation of the type alias itself. -// @has - '//*[@id="impl-TypedefStruct"]/h3' 'impl TypedefStruct' -// @has - '//*[@id="method.on_alias"]/h4' 'pub fn on_alias()' -// @has - '//*[@id="impl-GenericStruct%3CT%3E"]/h3' 'impl<T> GenericStruct<T>' -// @has - '//*[@id="method.on_gen"]/h4' 'pub fn on_gen(arg: T)' -// @has - '//*[@id="impl-Foo-for-GenericStruct%3CT%3E"]/h3' 'impl<T> Foo for GenericStruct<T>' -// This trait implementation doesn't match the type alias parameters so shouldn't appear in docs. -// @!has - '//h3' 'impl Bar for GenericStruct<u32> {}' -// Same goes for the `Deref` impl. -// @!has - '//h2' 'Methods from Deref<Target = u32>' -pub type TypedefStruct = GenericStruct<u8>; - -impl TypedefStruct { - pub fn on_alias() {} -} - -impl std::ops::Deref for GenericStruct<u32> { - type Target = u32; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -pub struct Wrap<T>(GenericStruct<T>); - -// @has 'foo/type.Alias.html' -// @has - '//h2' 'Methods from Deref<Target = u32>' -// @has - '//*[@id="impl-Deref-for-Wrap%3CT%3E"]/h3' 'impl<T> Deref for Wrap<T>' -pub type Alias = Wrap<u32>; - -impl<T> std::ops::Deref for Wrap<T> { - type Target = GenericStruct<T>; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} diff --git a/tests/ui/associated-inherent-types/private-in-public.rs b/tests/ui/associated-inherent-types/private-in-public.rs index a4b372537c7..44a20a79ad6 100644 --- a/tests/ui/associated-inherent-types/private-in-public.rs +++ b/tests/ui/associated-inherent-types/private-in-public.rs @@ -3,6 +3,11 @@ #![crate_type = "lib"] #![deny(private_in_public)] +#![warn(private_interfaces)] + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. pub type PubAlias0 = PubTy::PrivAssocTy; //~^ ERROR private associated type `PubTy::PrivAssocTy` in public interface (error E0446) diff --git a/tests/ui/associated-inherent-types/private-in-public.stderr b/tests/ui/associated-inherent-types/private-in-public.stderr index f0a64e96179..d40db83707b 100644 --- a/tests/ui/associated-inherent-types/private-in-public.stderr +++ b/tests/ui/associated-inherent-types/private-in-public.stderr @@ -1,5 +1,5 @@ error: private associated type `PubTy::PrivAssocTy` in public interface (error E0446) - --> $DIR/private-in-public.rs:7:1 + --> $DIR/private-in-public.rs:12:1 | LL | pub type PubAlias0 = PubTy::PrivAssocTy; | ^^^^^^^^^^^^^^^^^^ @@ -12,8 +12,26 @@ note: the lint level is defined here LL | #![deny(private_in_public)] | ^^^^^^^^^^^^^^^^^ +warning: associated type `PubTy::PrivAssocTy` is more private than the item `PubAlias0` + | +note: type alias `PubAlias0` is reachable at visibility `pub` + --> $DIR/private-in-public.rs:12:1 + | +LL | pub type PubAlias0 = PubTy::PrivAssocTy; + | ^^^^^^^^^^^^^^^^^^ +note: but associated type `PubTy::PrivAssocTy` is only usable at visibility `pub(crate)` + --> $DIR/private-in-public.rs:24:5 + | +LL | type PrivAssocTy = (); + | ^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/private-in-public.rs:6:9 + | +LL | #![warn(private_interfaces)] + | ^^^^^^^^^^^^^^^^^^ + error: private type `PrivTy` in public interface (error E0446) - --> $DIR/private-in-public.rs:10:1 + --> $DIR/private-in-public.rs:15:1 | LL | pub type PubAlias1 = PrivTy::PubAssocTy; | ^^^^^^^^^^^^^^^^^^ @@ -21,8 +39,21 @@ LL | pub type PubAlias1 = PrivTy::PubAssocTy; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> +warning: type `PrivTy` is more private than the item `PubAlias1` + | +note: type alias `PubAlias1` is reachable at visibility `pub` + --> $DIR/private-in-public.rs:15:1 + | +LL | pub type PubAlias1 = PrivTy::PubAssocTy; + | ^^^^^^^^^^^^^^^^^^ +note: but type `PrivTy` is only usable at visibility `pub(crate)` + --> $DIR/private-in-public.rs:28:1 + | +LL | struct PrivTy; + | ^^^^^^^^^^^^^ + error: private type `PrivTy` in public interface (error E0446) - --> $DIR/private-in-public.rs:13:1 + --> $DIR/private-in-public.rs:18:1 | LL | pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>; | ^^^^^^^^^^^^^^^^^^ @@ -30,5 +61,18 @@ LL | pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> -error: aborting due to 3 previous errors +warning: type `PrivTy` is more private than the item `PubAlias2` + | +note: type alias `PubAlias2` is reachable at visibility `pub` + --> $DIR/private-in-public.rs:18:1 + | +LL | pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>; + | ^^^^^^^^^^^^^^^^^^ +note: but type `PrivTy` is only usable at visibility `pub(crate)` + --> $DIR/private-in-public.rs:28:1 + | +LL | struct PrivTy; + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 3 warnings emitted diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs index 8023b998a40..96b769699cc 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.rs @@ -2,6 +2,12 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] +#![warn(private_interfaces)] + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. + pub struct Const<const U: u8>; pub trait Trait { diff --git a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr index 2d9de8805bb..465621619b4 100644 --- a/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr +++ b/tests/ui/const-generics/generic_const_exprs/eval-privacy.stderr @@ -1,5 +1,5 @@ error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface - --> $DIR/eval-privacy.rs:16:5 + --> $DIR/eval-privacy.rs:22:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; | ^^^^^^^^^^^^ can't leak private type @@ -7,6 +7,24 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to previous error +warning: type `fn(u8) -> u8 {my_const_fn}` is more private than the item `<Const<U> as Trait>::AssocTy` + | +note: associated type `<Const<U> as Trait>::AssocTy` is reachable at visibility `pub` + --> $DIR/eval-privacy.rs:22:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ +note: but type `fn(u8) -> u8 {my_const_fn}` is only usable at visibility `pub(crate)` + --> $DIR/eval-privacy.rs:29:1 + | +LL | const fn my_const_fn(val: u8) -> u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/eval-privacy.rs:5:9 + | +LL | #![warn(private_interfaces)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/error-codes/E0445.rs b/tests/ui/error-codes/E0445.rs index a9a3aee2500..f5f35fb8a4d 100644 --- a/tests/ui/error-codes/E0445.rs +++ b/tests/ui/error-codes/E0445.rs @@ -1,3 +1,10 @@ +#[warn(private_bounds)] +#[warn(private_interfaces)] + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. + trait Foo { fn dummy(&self) { } } diff --git a/tests/ui/error-codes/E0445.stderr b/tests/ui/error-codes/E0445.stderr index 23b7a335047..ac3637a8218 100644 --- a/tests/ui/error-codes/E0445.stderr +++ b/tests/ui/error-codes/E0445.stderr @@ -1,5 +1,5 @@ error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:5:1 + --> $DIR/E0445.rs:12:1 | LL | trait Foo { | --------- `Foo` declared as private @@ -7,8 +7,26 @@ LL | trait Foo { LL | pub trait Bar : Foo {} | ^^^^^^^^^^^^^^^^^^^ can't leak private trait +warning: trait `Foo` is more private than the item `Bar` + | +note: trait `Bar` is reachable at visibility `pub` + --> $DIR/E0445.rs:12:1 + | +LL | pub trait Bar : Foo {} + | ^^^^^^^^^^^^^^^^^^^ +note: but trait `Foo` is only usable at visibility `pub(crate)` + --> $DIR/E0445.rs:8:1 + | +LL | trait Foo { + | ^^^^^^^^^ +note: the lint level is defined here + --> $DIR/E0445.rs:1:8 + | +LL | #[warn(private_bounds)] + | ^^^^^^^^^^^^^^ + error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:7:1 + --> $DIR/E0445.rs:14:1 | LL | trait Foo { | --------- `Foo` declared as private @@ -16,8 +34,21 @@ LL | trait Foo { LL | pub struct Bar2<T: Foo>(pub T); | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait +warning: trait `Foo` is more private than the item `Bar2` + | +note: struct `Bar2` is reachable at visibility `pub` + --> $DIR/E0445.rs:14: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 + | +LL | trait Foo { + | ^^^^^^^^^ + error[E0445]: private trait `Foo` in public interface - --> $DIR/E0445.rs:9:1 + --> $DIR/E0445.rs:16:1 | LL | trait Foo { | --------- `Foo` declared as private @@ -25,6 +56,19 @@ LL | trait Foo { LL | pub fn foo<T: Foo> (t: T) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait -error: aborting due to 3 previous errors +warning: trait `Foo` is more private than the item `foo` + | +note: function `foo` is reachable at visibility `pub` + --> $DIR/E0445.rs:16: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 + | +LL | trait Foo { + | ^^^^^^^^^ + +error: aborting due to 3 previous errors; 3 warnings emitted For more information about this error, try `rustc --explain E0445`. diff --git a/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs b/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs new file mode 100644 index 00000000000..17e08f511d7 --- /dev/null +++ b/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.rs @@ -0,0 +1,10 @@ +extern "C" { + type Item = [T] where [T]: Sized; + //~^ incorrect `type` inside `extern` block + //~| `type`s inside `extern` blocks cannot have `where` clauses + //~| cannot find type `T` in this scope + //~| cannot find type `T` in this scope + //~| extern types are experimental +} + +fn main() {} diff --git a/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.stderr b/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.stderr new file mode 100644 index 00000000000..bdc6755038a --- /dev/null +++ b/tests/ui/extern/issue-112363-extern-item-where-clauses-debug-ice.stderr @@ -0,0 +1,47 @@ +error: incorrect `type` inside `extern` block + --> $DIR/issue-112363-extern-item-where-clauses-debug-ice.rs:2:10 + | +LL | extern "C" { + | ---------- `extern` blocks define existing foreign types and types inside of them cannot have a body +LL | type Item = [T] where [T]: Sized; + | ^^^^ --- the invalid body + | | + | cannot have a body + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/issue-112363-extern-item-where-clauses-debug-ice.rs:2:21 + | +LL | extern "C" { + | ---------- `extern` block begins here +LL | type Item = [T] where [T]: Sized; + | ^^^^^^^^^^^^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error[E0412]: cannot find type `T` in this scope + --> $DIR/issue-112363-extern-item-where-clauses-debug-ice.rs:2:28 + | +LL | type Item = [T] where [T]: Sized; + | ^ not found in this scope + +error[E0412]: cannot find type `T` in this scope + --> $DIR/issue-112363-extern-item-where-clauses-debug-ice.rs:2:18 + | +LL | type Item = [T] where [T]: Sized; + | ^ not found in this scope + +error[E0658]: extern types are experimental + --> $DIR/issue-112363-extern-item-where-clauses-debug-ice.rs:2:5 + | +LL | type Item = [T] where [T]: Sized; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #43467 <https://github.com/rust-lang/rust/issues/43467> for more information + = help: add `#![feature(extern_types)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0412, E0658. +For more information about an error, try `rustc --explain E0412`. diff --git a/tests/ui/issues/issue-18389.rs b/tests/ui/issues/issue-18389.rs index 654dfb63b88..3686afc48af 100644 --- a/tests/ui/issues/issue-18389.rs +++ b/tests/ui/issues/issue-18389.rs @@ -1,3 +1,9 @@ +#![warn(private_bounds)] + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. + use std::any::Any; use std::any::TypeId; diff --git a/tests/ui/issues/issue-18389.stderr b/tests/ui/issues/issue-18389.stderr index 6ce78c45d6e..f9ebde48a45 100644 --- a/tests/ui/issues/issue-18389.stderr +++ b/tests/ui/issues/issue-18389.stderr @@ -1,5 +1,5 @@ error[E0445]: private trait `Private<<Self as Public>::P, <Self as Public>::R>` in public interface - --> $DIR/issue-18389.rs:7:1 + --> $DIR/issue-18389.rs:13:1 | LL | trait Private<P, R> { | ------------------- `Private<<Self as Public>::P, <Self as Public>::R>` declared as private @@ -11,6 +11,28 @@ LL | | <Self as Public>::R LL | | > { | |_^ can't leak private trait -error: aborting due to previous error +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 + | +LL | / pub trait Public: Private< +LL | | +LL | | <Self as Public>::P, +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 + | +LL | trait Private<P, R> { + | ^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/issue-18389.rs:1:9 + | +LL | #![warn(private_bounds)] + | ^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0445`. diff --git a/tests/ui/parser/foreign-ty-semantic-fail.rs b/tests/ui/parser/foreign-ty-semantic-fail.rs index 96b15232b10..4d30086e765 100644 --- a/tests/ui/parser/foreign-ty-semantic-fail.rs +++ b/tests/ui/parser/foreign-ty-semantic-fail.rs @@ -15,4 +15,5 @@ extern "C" { //~^ ERROR incorrect `type` inside `extern` block type E: where; + //~^ ERROR `type`s inside `extern` blocks cannot have `where` clauses } diff --git a/tests/ui/parser/foreign-ty-semantic-fail.stderr b/tests/ui/parser/foreign-ty-semantic-fail.stderr index 588e4966aae..2b400dfea3b 100644 --- a/tests/ui/parser/foreign-ty-semantic-fail.stderr +++ b/tests/ui/parser/foreign-ty-semantic-fail.stderr @@ -61,5 +61,16 @@ LL | type D = u8; | = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html -error: aborting due to 6 previous errors +error: `type`s inside `extern` blocks cannot have `where` clauses + --> $DIR/foreign-ty-semantic-fail.rs:17:13 + | +LL | extern "C" { + | ---------- `extern` block begins here +... +LL | type E: where; + | ^^^^^ help: remove the `where` clause + | + = note: for more information, visit https://doc.rust-lang.org/std/keyword.extern.html + +error: aborting due to 7 previous errors diff --git a/tests/ui/privacy/private-in-public-non-principal.rs b/tests/ui/privacy/private-in-public-non-principal.rs index ac1d5a9e6a2..a80c1541463 100644 --- a/tests/ui/privacy/private-in-public-non-principal.rs +++ b/tests/ui/privacy/private-in-public-non-principal.rs @@ -1,6 +1,12 @@ #![feature(auto_traits)] #![feature(negative_impls)] +#![deny(private_interfaces)] + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. + pub trait PubPrincipal {} auto trait PrivNonPrincipal {} diff --git a/tests/ui/privacy/private-in-public-non-principal.stderr b/tests/ui/privacy/private-in-public-non-principal.stderr index de20cada42e..9fc12affe4b 100644 --- a/tests/ui/privacy/private-in-public-non-principal.stderr +++ b/tests/ui/privacy/private-in-public-non-principal.stderr @@ -1,5 +1,5 @@ warning: private trait `PrivNonPrincipal` in public interface (error E0445) - --> $DIR/private-in-public-non-principal.rs:7:1 + --> $DIR/private-in-public-non-principal.rs:13:1 | LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,17 +8,35 @@ LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> = note: `#[warn(private_in_public)]` on by default +error: trait `PrivNonPrincipal` is more private than the item `leak_dyn_nonprincipal` + | +note: function `leak_dyn_nonprincipal` is reachable at visibility `pub` + --> $DIR/private-in-public-non-principal.rs:13:1 + | +LL | pub fn leak_dyn_nonprincipal() -> Box<dyn PubPrincipal + PrivNonPrincipal> { loop {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: but trait `PrivNonPrincipal` is only usable at visibility `pub(crate)` + --> $DIR/private-in-public-non-principal.rs:11:1 + | +LL | auto trait PrivNonPrincipal {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/private-in-public-non-principal.rs:4:9 + | +LL | #![deny(private_interfaces)] + | ^^^^^^^^^^^^^^^^^^ + error: missing documentation for an associated function - --> $DIR/private-in-public-non-principal.rs:14:9 + --> $DIR/private-in-public-non-principal.rs:20:9 | LL | pub fn check_doc_lint() {} | ^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/private-in-public-non-principal.rs:11:8 + --> $DIR/private-in-public-non-principal.rs:17:8 | LL | #[deny(missing_docs)] | ^^^^^^^^^^^^ -error: aborting due to previous error; 1 warning emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/privacy/private-inferred-type-1.rs b/tests/ui/privacy/private-inferred-type-1.rs index d633189e3fb..b3eba53dd13 100644 --- a/tests/ui/privacy/private-inferred-type-1.rs +++ b/tests/ui/privacy/private-inferred-type-1.rs @@ -5,14 +5,24 @@ trait TyParam { fn ty_param_secret(&self); } +trait Ref { + fn ref_secret(self); +} + mod m { struct Priv; impl ::Arr0 for [Priv; 0] { fn arr0_secret(&self) {} } impl ::TyParam for Option<Priv> { fn ty_param_secret(&self) {} } + impl<'a> ::Ref for &'a Priv { fn ref_secret(self) {} } } +fn anyref<'a, T>() -> &'a T { panic!() } + fn main() { [].arr0_secret(); //~ ERROR type `Priv` is private None.ty_param_secret(); //~ ERROR type `Priv` is private + Ref::ref_secret(anyref()); + //~^ ERROR type `Priv` is private + //~| ERROR type `Priv` is private } diff --git a/tests/ui/privacy/private-inferred-type-1.stderr b/tests/ui/privacy/private-inferred-type-1.stderr index 245789f4353..47c11d6ec76 100644 --- a/tests/ui/privacy/private-inferred-type-1.stderr +++ b/tests/ui/privacy/private-inferred-type-1.stderr @@ -1,14 +1,26 @@ error: type `Priv` is private - --> $DIR/private-inferred-type-1.rs:16:5 + --> $DIR/private-inferred-type-1.rs:23:5 | LL | [].arr0_secret(); | ^^^^^^^^^^^^^^^^ private type error: type `Priv` is private - --> $DIR/private-inferred-type-1.rs:17:5 + --> $DIR/private-inferred-type-1.rs:24:5 | LL | None.ty_param_secret(); | ^^^^^^^^^^^^^^^^^^^^^^ private type -error: aborting due to 2 previous errors +error: type `Priv` is private + --> $DIR/private-inferred-type-1.rs:25:5 + | +LL | Ref::ref_secret(anyref()); + | ^^^^^^^^^^^^^^^ private type + +error: type `Priv` is private + --> $DIR/private-inferred-type-1.rs:25:21 + | +LL | Ref::ref_secret(anyref()); + | ^^^^^^^^ private type + +error: aborting due to 4 previous errors diff --git a/tests/ui/privacy/unnameable_types.rs b/tests/ui/privacy/unnameable_types.rs new file mode 100644 index 00000000000..8b53f372fc9 --- /dev/null +++ b/tests/ui/privacy/unnameable_types.rs @@ -0,0 +1,30 @@ +#![allow(unused)] +#![allow(private_in_public)] +#![deny(unnameable_types)] + +mod m { + pub struct PubStruct(pub i32); //~ ERROR struct `PubStruct` is reachable but cannot be named + + pub enum PubE { //~ ERROR enum `PubE` is reachable but cannot be named + V(i32), + } + + pub trait PubTr { //~ ERROR trait `PubTr` is reachable but cannot be named + const C : i32 = 0; + type Alias; //~ ERROR associated type `PubTr::Alias` is reachable but cannot be named + fn f() {} + } + + impl PubTr for PubStruct { + type Alias = i32; //~ ERROR associated type `<PubStruct as PubTr>::Alias` is reachable but cannot be named + fn f() {} + } +} + +pub trait Voldemort<T> {} + +impl Voldemort<m::PubStruct> for i32 {} +impl Voldemort<m::PubE> for i32 {} +impl<T> Voldemort<T> for u32 where T: m::PubTr {} + +fn main() {} diff --git a/tests/ui/privacy/unnameable_types.stderr b/tests/ui/privacy/unnameable_types.stderr new file mode 100644 index 00000000000..25eb5c9434a --- /dev/null +++ b/tests/ui/privacy/unnameable_types.stderr @@ -0,0 +1,38 @@ +error: struct `PubStruct` is reachable but cannot be named + --> $DIR/unnameable_types.rs:6:5 + | +LL | pub struct PubStruct(pub i32); + | ^^^^^^^^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)` + | +note: the lint level is defined here + --> $DIR/unnameable_types.rs:3:9 + | +LL | #![deny(unnameable_types)] + | ^^^^^^^^^^^^^^^^ + +error: enum `PubE` is reachable but cannot be named + --> $DIR/unnameable_types.rs:8:5 + | +LL | pub enum PubE { + | ^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)` + +error: trait `PubTr` is reachable but cannot be named + --> $DIR/unnameable_types.rs:12:5 + | +LL | pub trait PubTr { + | ^^^^^^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)` + +error: associated type `PubTr::Alias` is reachable but cannot be named + --> $DIR/unnameable_types.rs:14:9 + | +LL | type Alias; + | ^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)` + +error: associated type `<PubStruct as PubTr>::Alias` is reachable but cannot be named + --> $DIR/unnameable_types.rs:19:9 + | +LL | type Alias = i32; + | ^^^^^^^^^^ reachable at visibility `pub`, but can only be named at visibility `pub(crate)` + +error: aborting due to 5 previous errors + diff --git a/tests/ui/privacy/where-priv-type.rs b/tests/ui/privacy/where-priv-type.rs index 66ee9c4bbd8..9899902dd88 100644 --- a/tests/ui/privacy/where-priv-type.rs +++ b/tests/ui/privacy/where-priv-type.rs @@ -5,6 +5,12 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] +#![warn(private_bounds)] +#![warn(private_interfaces)] + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. struct PrivTy; trait PrivTr {} diff --git a/tests/ui/privacy/where-priv-type.stderr b/tests/ui/privacy/where-priv-type.stderr index c5fb2cdb0cf..2830fa6cd44 100644 --- a/tests/ui/privacy/where-priv-type.stderr +++ b/tests/ui/privacy/where-priv-type.stderr @@ -1,5 +1,5 @@ warning: private type `PrivTy` in public interface (error E0446) - --> $DIR/where-priv-type.rs:19:1 + --> $DIR/where-priv-type.rs:25:1 | LL | pub struct S | ^^^^^^^^^^^^ @@ -8,8 +8,26 @@ LL | pub struct S = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> = note: `#[warn(private_in_public)]` on by default +warning: type `PrivTy` is more private than the item `S` + | +note: struct `S` is reachable at visibility `pub` + --> $DIR/where-priv-type.rs:25:1 + | +LL | pub struct S + | ^^^^^^^^^^^^ +note: but type `PrivTy` is only usable at visibility `pub(crate)` + --> $DIR/where-priv-type.rs:15:1 + | +LL | struct PrivTy; + | ^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/where-priv-type.rs:8:9 + | +LL | #![warn(private_bounds)] + | ^^^^^^^^^^^^^^ + warning: private type `PrivTy` in public interface (error E0446) - --> $DIR/where-priv-type.rs:27:1 + --> $DIR/where-priv-type.rs:33:1 | LL | pub enum E | ^^^^^^^^^^ @@ -17,8 +35,21 @@ LL | pub enum E = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> +warning: type `PrivTy` is more private than the item `E` + | +note: enum `E` is reachable at visibility `pub` + --> $DIR/where-priv-type.rs:33:1 + | +LL | pub enum E + | ^^^^^^^^^^ +note: but type `PrivTy` is only usable at visibility `pub(crate)` + --> $DIR/where-priv-type.rs:15:1 + | +LL | struct PrivTy; + | ^^^^^^^^^^^^^ + warning: private type `PrivTy` in public interface (error E0446) - --> $DIR/where-priv-type.rs:35:1 + --> $DIR/where-priv-type.rs:41:1 | LL | / pub fn f() LL | | @@ -30,8 +61,25 @@ LL | | PrivTy: = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> +warning: type `PrivTy` is more private than the item `f` + | +note: function `f` is reachable at visibility `pub` + --> $DIR/where-priv-type.rs:41:1 + | +LL | / pub fn f() +LL | | +LL | | +LL | | where +LL | | PrivTy: + | |___________^ +note: but type `PrivTy` is only usable at visibility `pub(crate)` + --> $DIR/where-priv-type.rs:15:1 + | +LL | struct PrivTy; + | ^^^^^^^^^^^^^ + error[E0446]: private type `PrivTy` in public interface - --> $DIR/where-priv-type.rs:43:1 + --> $DIR/where-priv-type.rs:49:1 | LL | struct PrivTy; | ------------- `PrivTy` declared as private @@ -39,8 +87,21 @@ LL | struct PrivTy; LL | impl S | ^^^^^^ can't leak private type +warning: type `PrivTy` is more private than the item `S` + | +note: implementation `S` is reachable at visibility `pub` + --> $DIR/where-priv-type.rs:49:1 + | +LL | impl S + | ^^^^^^ +note: but type `PrivTy` is only usable at visibility `pub(crate)` + --> $DIR/where-priv-type.rs:15:1 + | +LL | struct PrivTy; + | ^^^^^^^^^^^^^ + warning: private type `PrivTy` in public interface (error E0446) - --> $DIR/where-priv-type.rs:48:5 + --> $DIR/where-priv-type.rs:54:5 | LL | / pub fn f() LL | | @@ -52,8 +113,25 @@ LL | | PrivTy: = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> +warning: type `PrivTy` is more private than the item `S::f` + | +note: associated function `S::f` is reachable at visibility `pub` + --> $DIR/where-priv-type.rs:54:5 + | +LL | / pub fn f() +LL | | +LL | | +LL | | where +LL | | PrivTy: + | |_______________^ +note: but type `PrivTy` is only usable at visibility `pub(crate)` + --> $DIR/where-priv-type.rs:15:1 + | +LL | struct PrivTy; + | ^^^^^^^^^^^^^ + error[E0446]: private type `fn(u8) -> u8 {my_const_fn}` in public interface - --> $DIR/where-priv-type.rs:80:5 + --> $DIR/where-priv-type.rs:86:5 | LL | type AssocTy = Const<{ my_const_fn(U) }>; | ^^^^^^^^^^^^ can't leak private type @@ -61,6 +139,24 @@ LL | type AssocTy = Const<{ my_const_fn(U) }>; LL | const fn my_const_fn(val: u8) -> u8 { | ----------------------------------- `fn(u8) -> u8 {my_const_fn}` declared as private -error: aborting due to 2 previous errors; 4 warnings emitted +warning: type `fn(u8) -> u8 {my_const_fn}` is more private than the item `<Const<U> as Trait>::AssocTy` + | +note: associated type `<Const<U> as Trait>::AssocTy` is reachable at visibility `pub` + --> $DIR/where-priv-type.rs:86:5 + | +LL | type AssocTy = Const<{ my_const_fn(U) }>; + | ^^^^^^^^^^^^ +note: but type `fn(u8) -> u8 {my_const_fn}` is only usable at visibility `pub(crate)` + --> $DIR/where-priv-type.rs:93:1 + | +LL | const fn my_const_fn(val: u8) -> u8 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/where-priv-type.rs:9:9 + | +LL | #![warn(private_interfaces)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors; 10 warnings emitted For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs index 87c211df169..3aad893eae2 100644 --- a/tests/ui/privacy/where-pub-type-impls-priv-trait.rs +++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.rs @@ -4,6 +4,11 @@ #![feature(generic_const_exprs)] #![allow(incomplete_features)] +#![warn(private_bounds)] + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. struct PrivTy; trait PrivTr {} diff --git a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr index a433cebbbc0..413f7f781cd 100644 --- a/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr +++ b/tests/ui/privacy/where-pub-type-impls-priv-trait.stderr @@ -1,5 +1,5 @@ error[E0445]: private trait `PrivTr` in public interface - --> $DIR/where-pub-type-impls-priv-trait.rs:19:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:24:1 | LL | trait PrivTr {} | ------------ `PrivTr` declared as private @@ -7,8 +7,26 @@ LL | trait PrivTr {} LL | pub struct S | ^^^^^^^^^^^^ can't leak private trait +warning: trait `PrivTr` is more private than the item `S` + | +note: struct `S` is reachable at visibility `pub` + --> $DIR/where-pub-type-impls-priv-trait.rs:24:1 + | +LL | pub struct S + | ^^^^^^^^^^^^ +note: but trait `PrivTr` is only usable at visibility `pub(crate)` + --> $DIR/where-pub-type-impls-priv-trait.rs:14:1 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/where-pub-type-impls-priv-trait.rs:7:9 + | +LL | #![warn(private_bounds)] + | ^^^^^^^^^^^^^^ + error[E0445]: private trait `PrivTr` in public interface - --> $DIR/where-pub-type-impls-priv-trait.rs:26:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:31:1 | LL | trait PrivTr {} | ------------ `PrivTr` declared as private @@ -16,8 +34,21 @@ LL | trait PrivTr {} LL | pub enum E | ^^^^^^^^^^ can't leak private trait +warning: trait `PrivTr` is more private than the item `E` + | +note: enum `E` is reachable at visibility `pub` + --> $DIR/where-pub-type-impls-priv-trait.rs:31:1 + | +LL | pub enum E + | ^^^^^^^^^^ +note: but trait `PrivTr` is only usable at visibility `pub(crate)` + --> $DIR/where-pub-type-impls-priv-trait.rs:14:1 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + error[E0445]: private trait `PrivTr` in public interface - --> $DIR/where-pub-type-impls-priv-trait.rs:33:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:38:1 | LL | trait PrivTr {} | ------------ `PrivTr` declared as private @@ -28,8 +59,24 @@ LL | | where LL | | PubTy: PrivTr | |_________________^ can't leak private trait +warning: trait `PrivTr` is more private than the item `f` + | +note: function `f` is reachable at visibility `pub` + --> $DIR/where-pub-type-impls-priv-trait.rs:38:1 + | +LL | / pub fn f() +LL | | +LL | | where +LL | | PubTy: PrivTr + | |_________________^ +note: but trait `PrivTr` is only usable at visibility `pub(crate)` + --> $DIR/where-pub-type-impls-priv-trait.rs:14:1 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + error[E0445]: private trait `PrivTr` in public interface - --> $DIR/where-pub-type-impls-priv-trait.rs:40:1 + --> $DIR/where-pub-type-impls-priv-trait.rs:45:1 | LL | trait PrivTr {} | ------------ `PrivTr` declared as private @@ -37,8 +84,21 @@ LL | trait PrivTr {} LL | impl S | ^^^^^^ can't leak private trait +warning: trait `PrivTr` is more private than the item `S` + | +note: implementation `S` is reachable at visibility `pub` + --> $DIR/where-pub-type-impls-priv-trait.rs:45:1 + | +LL | impl S + | ^^^^^^ +note: but trait `PrivTr` is only usable at visibility `pub(crate)` + --> $DIR/where-pub-type-impls-priv-trait.rs:14:1 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + error[E0445]: private trait `PrivTr` in public interface - --> $DIR/where-pub-type-impls-priv-trait.rs:45:5 + --> $DIR/where-pub-type-impls-priv-trait.rs:50:5 | LL | trait PrivTr {} | ------------ `PrivTr` declared as private @@ -49,6 +109,22 @@ LL | | where LL | | PubTy: PrivTr | |_____________________^ can't leak private trait -error: aborting due to 5 previous errors +warning: trait `PrivTr` is more private than the item `S::f` + | +note: associated function `S::f` is reachable at visibility `pub` + --> $DIR/where-pub-type-impls-priv-trait.rs:50:5 + | +LL | / pub fn f() +LL | | +LL | | where +LL | | PubTy: PrivTr + | |_____________________^ +note: but trait `PrivTr` is only usable at visibility `pub(crate)` + --> $DIR/where-pub-type-impls-priv-trait.rs:14:1 + | +LL | trait PrivTr {} + | ^^^^^^^^^^^^ + +error: aborting due to 5 previous errors; 5 warnings emitted For more information about this error, try `rustc --explain E0445`. diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs index 67f888c5e94..9e4ba80a784 100644 --- a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs +++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.rs @@ -1,15 +1,24 @@ #![allow(non_camel_case_types)] // genus is always capitalized +#![warn(private_interfaces)] +//~^ NOTE the lint level is defined here + +// In this test both old and new private-in-public diagnostic were emitted. +// Old diagnostic will be deleted soon. +// See https://rust-lang.github.io/rfcs/2145-type-privacy.html. pub(crate) struct Snail; //~^ NOTE `Snail` declared as private +//~| NOTE but type `Snail` is only usable at visibility `pub(crate)` mod sea { pub(super) struct Turtle; //~^ NOTE `Turtle` declared as crate-private + //~| NOTE but type `Turtle` is only usable at visibility `pub(crate)` } struct Tortoise; //~^ NOTE `Tortoise` declared as private +//~| NOTE but type `Tortoise` is only usable at visibility `pub(crate)` pub struct Shell<T> { pub(crate) creature: T, @@ -18,11 +27,14 @@ pub struct Shell<T> { pub type Helix_pomatia = Shell<Snail>; //~^ ERROR private type `Snail` in public interface //~| NOTE can't leak private type +//~| NOTE type alias `Helix_pomatia` is reachable at visibility `pub` pub type Dermochelys_coriacea = Shell<sea::Turtle>; //~^ ERROR crate-private type `Turtle` in public interface //~| NOTE can't leak crate-private type +//~| NOTE type alias `Dermochelys_coriacea` is reachable at visibility `pub` pub type Testudo_graeca = Shell<Tortoise>; //~^ ERROR private type `Tortoise` in public interface //~| NOTE can't leak private type +//~| NOTE type alias `Testudo_graeca` is reachable at visibility `pub` fn main() {} diff --git a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr index 39d4f5ac8d3..52f67d4cdd5 100644 --- a/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr +++ b/tests/ui/pub/issue-33174-restricted-type-in-public-interface.stderr @@ -1,5 +1,5 @@ error[E0446]: private type `Snail` in public interface - --> $DIR/issue-33174-restricted-type-in-public-interface.rs:18:1 + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:27:1 | LL | pub(crate) struct Snail; | ----------------------- `Snail` declared as private @@ -7,8 +7,26 @@ LL | pub(crate) struct Snail; LL | pub type Helix_pomatia = Shell<Snail>; | ^^^^^^^^^^^^^^^^^^^^^^ can't leak private type +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 + | +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 + | +LL | pub(crate) struct Snail; + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: the lint level is defined here + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:2:9 + | +LL | #![warn(private_interfaces)] + | ^^^^^^^^^^^^^^^^^^ + error[E0446]: crate-private type `Turtle` in public interface - --> $DIR/issue-33174-restricted-type-in-public-interface.rs:21:1 + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:31:1 | LL | pub(super) struct Turtle; | ------------------------ `Turtle` declared as crate-private @@ -16,8 +34,21 @@ LL | pub(super) struct Turtle; LL | pub type Dermochelys_coriacea = Shell<sea::Turtle>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak crate-private type +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 + | +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 + | +LL | pub(super) struct Turtle; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + error[E0446]: private type `Tortoise` in public interface - --> $DIR/issue-33174-restricted-type-in-public-interface.rs:24:1 + --> $DIR/issue-33174-restricted-type-in-public-interface.rs:35:1 | LL | struct Tortoise; | --------------- `Tortoise` declared as private @@ -25,6 +56,19 @@ LL | struct Tortoise; LL | pub type Testudo_graeca = Shell<Tortoise>; | ^^^^^^^^^^^^^^^^^^^^^^^ can't leak private type -error: aborting due to 3 previous errors +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 + | +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 + | +LL | struct Tortoise; + | ^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 3 warnings emitted For more information about this error, try `rustc --explain E0446`. diff --git a/tests/ui/typeck/issue-112252-ptr-arithmetics-help.fixed b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.fixed new file mode 100644 index 00000000000..bdb884f5431 --- /dev/null +++ b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.fixed @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _ptr1: *const u32 = std::ptr::null(); + let _ptr2: *const u32 = std::ptr::null(); + let _a = _ptr1.wrapping_add(5); //~ ERROR cannot add + let _b = _ptr1.wrapping_sub(5); //~ ERROR cannot subtract + let _c = unsafe { _ptr2.offset_from(_ptr1) }; //~ ERROR cannot subtract + let _d = _ptr1.wrapping_add(5); //~ ERROR cannot index +} diff --git a/tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs new file mode 100644 index 00000000000..cf68850cc4d --- /dev/null +++ b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.rs @@ -0,0 +1,10 @@ +// run-rustfix + +fn main() { + let _ptr1: *const u32 = std::ptr::null(); + let _ptr2: *const u32 = std::ptr::null(); + let _a = _ptr1 + 5; //~ ERROR cannot add + let _b = _ptr1 - 5; //~ ERROR cannot subtract + let _c = _ptr2 - _ptr1; //~ ERROR cannot subtract + let _d = _ptr1[5]; //~ ERROR cannot index +} diff --git a/tests/ui/typeck/issue-112252-ptr-arithmetics-help.stderr b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.stderr new file mode 100644 index 00000000000..c55930da225 --- /dev/null +++ b/tests/ui/typeck/issue-112252-ptr-arithmetics-help.stderr @@ -0,0 +1,54 @@ +error[E0369]: cannot add `{integer}` to `*const u32` + --> $DIR/issue-112252-ptr-arithmetics-help.rs:6:20 + | +LL | let _a = _ptr1 + 5; + | ----- ^ - {integer} + | | + | *const u32 + | +help: consider using `wrapping_add` or `add` for pointer + {integer} + | +LL | let _a = _ptr1.wrapping_add(5); + | ~~~~~~~~~~~~~~ + + +error[E0369]: cannot subtract `{integer}` from `*const u32` + --> $DIR/issue-112252-ptr-arithmetics-help.rs:7:20 + | +LL | let _b = _ptr1 - 5; + | ----- ^ - {integer} + | | + | *const u32 + | +help: consider using `wrapping_sub` or `sub` for pointer - {integer} + | +LL | let _b = _ptr1.wrapping_sub(5); + | ~~~~~~~~~~~~~~ + + +error[E0369]: cannot subtract `*const u32` from `*const u32` + --> $DIR/issue-112252-ptr-arithmetics-help.rs:8:20 + | +LL | let _c = _ptr2 - _ptr1; + | ----- ^ ----- *const u32 + | | + | *const u32 + | +help: consider using `offset_from` for pointer - pointer if the pointers point to the same allocation + | +LL | let _c = unsafe { _ptr2.offset_from(_ptr1) }; + | ++++++++ ~~~~~~~~~~~~~ +++ + +error[E0608]: cannot index into a value of type `*const u32` + --> $DIR/issue-112252-ptr-arithmetics-help.rs:9:14 + | +LL | let _d = _ptr1[5]; + | ^^^^^^^^ + | +help: consider using `wrapping_add` or `add` for indexing into raw pointer + | +LL | let _d = _ptr1.wrapping_add(5); + | ~~~~~~~~~~~~~~ ~ + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0369, E0608. +For more information about an error, try `rustc --explain E0369`. diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.fixed b/tests/ui/typeck/ptr-null-mutability-suggestions.fixed new file mode 100644 index 00000000000..d00536b29cf --- /dev/null +++ b/tests/ui/typeck/ptr-null-mutability-suggestions.fixed @@ -0,0 +1,11 @@ +// run-rustfix + +#[allow(unused_imports)] +use std::ptr; + +fn expecting_null_mut(_: *mut u8) {} + +fn main() { + expecting_null_mut(core::ptr::null_mut()); + //~^ ERROR mismatched types +} diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.rs b/tests/ui/typeck/ptr-null-mutability-suggestions.rs new file mode 100644 index 00000000000..ea3066d2289 --- /dev/null +++ b/tests/ui/typeck/ptr-null-mutability-suggestions.rs @@ -0,0 +1,11 @@ +// run-rustfix + +#[allow(unused_imports)] +use std::ptr; + +fn expecting_null_mut(_: *mut u8) {} + +fn main() { + expecting_null_mut(ptr::null()); + //~^ ERROR mismatched types +} diff --git a/tests/ui/typeck/ptr-null-mutability-suggestions.stderr b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr new file mode 100644 index 00000000000..705b029bdea --- /dev/null +++ b/tests/ui/typeck/ptr-null-mutability-suggestions.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/ptr-null-mutability-suggestions.rs:9:24 + | +LL | expecting_null_mut(ptr::null()); + | ------------------ ^^^^^^^^^^^ + | | | + | | types differ in mutability + | | help: consider using `core::ptr::null_mut` instead: `core::ptr::null_mut()` + | arguments to this function are incorrect + | + = note: expected raw pointer `*mut u8` + found raw pointer `*const _` +note: function defined here + --> $DIR/ptr-null-mutability-suggestions.rs:6:4 + | +LL | fn expecting_null_mut(_: *mut u8) {} + | ^^^^^^^^^^^^^^^^^^ ---------- + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/unsized-locals/rust-call.rs b/tests/ui/unsized-locals/rust-call.rs new file mode 100644 index 00000000000..ff4075aa4c0 --- /dev/null +++ b/tests/ui/unsized-locals/rust-call.rs @@ -0,0 +1,12 @@ +#![feature(unsized_tuple_coercion)] +#![feature(unboxed_closures)] +#![feature(unsized_fn_params)] + +fn bad() -> extern "rust-call" fn(([u8],)) { todo!() } + +fn main() { + let f = bad(); + let slice: Box<([u8],)> = Box::new(([1; 8],)); + f(*slice); + //~^ ERROR the size for values of type `[u8]` cannot be known at compilation time +} diff --git a/tests/ui/unsized-locals/rust-call.stderr b/tests/ui/unsized-locals/rust-call.stderr new file mode 100644 index 00000000000..fff7ef75b33 --- /dev/null +++ b/tests/ui/unsized-locals/rust-call.stderr @@ -0,0 +1,13 @@ +error[E0277]: the size for values of type `[u8]` cannot be known at compilation time + --> $DIR/rust-call.rs:10:7 + | +LL | f(*slice); + | ^^^^^^ doesn't have a size known at compile-time + | + = help: within `([u8],)`, the trait `Sized` is not implemented for `[u8]` + = note: required because it appears within the type `([u8],)` + = note: argument required to be sized due to `extern "rust-call"` ABI + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. |
