Auto merge of #81304 - jonas-schievink:rollup-d9kuugm, r=jonas-schievink

Rollup of 15 pull requests

Successful merges:

 - #79841 (More clear documentation for NonNull<T>)
 - #81072 (PlaceRef::ty: use method call syntax)
 - #81130 (Edit rustc_middle::dep_graph module documentation)
 - #81170 (Avoid hash_slice in VecDeque's Hash implementation)
 - #81243 (mir: Improve size_of handling when arg is unsized)
 - #81245 (Update cargo)
 - #81249 (Lower closure prototype after its body.)
 - #81252 (Add more self-profile info to rustc_resolve)
 - #81275 (Fix <unknown> queries and add more timing info to render_html)
 - #81281 (Inline methods of Path and OsString)
 - #81283 (Note library tracking issue template in tracking issue template.)
 - #81285 (Remove special casing of rustdoc in rustc_lint)
 - #81288 (rustdoc: Fix visibility of trait and impl items)
 - #81298 (replace RefCell with Cell in FnCtxt)
 - #81301 (Fix small typo)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2021-01-23 21:13:14 +00:00
commit 1279b3b923
37 changed files with 433 additions and 111 deletions

View File

@ -5,6 +5,8 @@ title: Tracking Issue for XXX
labels: C-tracking-issue labels: C-tracking-issue
--- ---
<!-- <!--
NOTE: For library features, please use the "Library Tracking Issue" template instead.
Thank you for creating a tracking issue! 📜 Tracking issues are for tracking a Thank you for creating a tracking issue! 📜 Tracking issues are for tracking a
feature from implementation to stabilisation. Make sure to include the relevant feature from implementation to stabilisation. Make sure to include the relevant
RFC for the feature if it has one. Otherwise provide a short summary of the RFC for the feature if it has one. Otherwise provide a short summary of the

View File

@ -427,6 +427,7 @@ dependencies = [
"remove_dir_all", "remove_dir_all",
"serde_json", "serde_json",
"tar", "tar",
"toml",
"url 2.1.1", "url 2.1.1",
] ]

View File

@ -776,10 +776,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
body: &Expr, body: &Expr,
fn_decl_span: Span, fn_decl_span: Span,
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
// Lower outside new scope to preserve `is_in_loop_condition`. let (body_id, generator_option) = self.with_new_scopes(move |this| {
let fn_decl = self.lower_fn_decl(decl, None, false, None);
self.with_new_scopes(move |this| {
let prev = this.current_item; let prev = this.current_item;
this.current_item = Some(fn_decl_span); this.current_item = Some(fn_decl_span);
let mut generator_kind = None; let mut generator_kind = None;
@ -791,8 +788,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
let generator_option = let generator_option =
this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability); this.generator_movability_for_fn(&decl, fn_decl_span, generator_kind, movability);
this.current_item = prev; this.current_item = prev;
hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option) (body_id, generator_option)
}) });
// Lower outside new scope to preserve `is_in_loop_condition`.
let fn_decl = self.lower_fn_decl(decl, None, false, None);
hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, generator_option)
} }
fn generator_movability_for_fn( fn generator_movability_for_fn(
@ -838,12 +840,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
) -> hir::ExprKind<'hir> { ) -> hir::ExprKind<'hir> {
let outer_decl = let outer_decl =
FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) }; FnDecl { inputs: decl.inputs.clone(), output: FnRetTy::Default(fn_decl_span) };
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
self.with_new_scopes(move |this| { let body_id = self.with_new_scopes(|this| {
// FIXME(cramertj): allow `async` non-`move` closures with arguments. // FIXME(cramertj): allow `async` non-`move` closures with arguments.
if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() { if capture_clause == CaptureBy::Ref && !decl.inputs.is_empty() {
struct_span_err!( struct_span_err!(
@ -874,8 +872,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
); );
this.expr(fn_decl_span, async_body, ThinVec::new()) this.expr(fn_decl_span, async_body, ThinVec::new())
}); });
hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None) body_id
}) });
// We need to lower the declaration outside the new scope, because we
// have to conserve the state of being inside a loop condition for the
// closure argument types.
let fn_decl = self.lower_fn_decl(&outer_decl, None, false, None);
hir::ExprKind::Closure(capture_clause, fn_decl, body_id, fn_decl_span, None)
} }
/// Destructure the LHS of complex assignments. /// Destructure the LHS of complex assignments.

View File

@ -119,7 +119,7 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
) )
); );
if is_consume { if is_consume {
let base_ty = mir::PlaceRef::ty(&place_base, self.fx.mir, cx.tcx()); let base_ty = place_base.ty(self.fx.mir, cx.tcx());
let base_ty = self.fx.monomorphize(base_ty); let base_ty = self.fx.monomorphize(base_ty);
// ZSTs don't require any actual memory access. // ZSTs don't require any actual memory access.

View File

@ -506,7 +506,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> { pub fn monomorphized_place_ty(&self, place_ref: mir::PlaceRef<'tcx>) -> Ty<'tcx> {
let tcx = self.cx.tcx(); let tcx = self.cx.tcx();
let place_ty = mir::PlaceRef::ty(&place_ref, self.mir, tcx); let place_ty = place_ref.ty(self.mir, tcx);
self.monomorphize(place_ty.ty) self.monomorphize(place_ty.ty)
} }
} }

View File

@ -1017,13 +1017,6 @@ pub fn start_codegen<'tcx>(
tcx.sess.time("assert_dep_graph", || rustc_incremental::assert_dep_graph(tcx)); tcx.sess.time("assert_dep_graph", || rustc_incremental::assert_dep_graph(tcx));
tcx.sess.time("serialize_dep_graph", || rustc_incremental::save_dep_graph(tcx)); tcx.sess.time("serialize_dep_graph", || rustc_incremental::save_dep_graph(tcx));
// We assume that no queries are run past here. If there are new queries
// after this point, they'll show up as "<unknown>" in self-profiling data.
{
let _prof_timer = tcx.prof.generic_activity("self_profile_alloc_query_strings");
tcx.alloc_self_profile_query_strings();
}
info!("Post-codegen\n{:?}", tcx.debug_stats()); info!("Post-codegen\n{:?}", tcx.debug_stats());
if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) {

View File

@ -417,9 +417,19 @@ impl Compiler {
let queries = Queries::new(&self); let queries = Queries::new(&self);
let ret = f(&queries); let ret = f(&queries);
if self.session().opts.debugging_opts.query_stats { // NOTE: intentionally does not compute the global context if it hasn't been built yet,
if let Ok(gcx) = queries.global_ctxt() { // since that likely means there was a parse error.
gcx.peek_mut().print_stats(); if let Some(Ok(gcx)) = &mut *queries.global_ctxt.result.borrow_mut() {
// We assume that no queries are run past here. If there are new queries
// after this point, they'll show up as "<unknown>" in self-profiling data.
{
let _prof_timer =
queries.session().prof.generic_activity("self_profile_alloc_query_strings");
gcx.enter(|tcx| tcx.alloc_self_profile_query_strings());
}
if self.session().opts.debugging_opts.query_stats {
gcx.print_stats();
} }
} }

View File

@ -379,17 +379,9 @@ pub fn check_ast_crate<T: EarlyLintPass>(
// All of the buffered lints should have been emitted at this point. // All of the buffered lints should have been emitted at this point.
// If not, that means that we somehow buffered a lint for a node id // If not, that means that we somehow buffered a lint for a node id
// that was not lint-checked (perhaps it doesn't exist?). This is a bug. // that was not lint-checked (perhaps it doesn't exist?). This is a bug.
// for (_id, lints) in buffered.map {
// Rustdoc runs everybody-loops before the early lints and removes for early_lint in lints {
// function bodies, so it's totally possible for linted sess.delay_span_bug(early_lint.span, "failed to process buffered lint here");
// node ids to not exist (e.g., macros defined within functions for the
// unused_macro lint) anymore. So we only run this check
// when we're not in rustdoc mode. (see issue #47639)
if !sess.opts.actually_rustdoc {
for (_id, lints) in buffered.map {
for early_lint in lints {
sess.delay_span_bug(early_lint.span, "failed to process buffered lint here");
}
} }
} }
} }

View File

@ -1,16 +1,17 @@
//! This module defines the `DepNode` type which the compiler uses to represent //! Nodes in the dependency graph.
//! nodes in the dependency graph.
//! //!
//! A `DepNode` consists of a `DepKind` (which //! A node in the [dependency graph] is represented by a [`DepNode`].
//! specifies the kind of thing it represents, like a piece of HIR, MIR, etc) //! A `DepNode` consists of a [`DepKind`] (which
//! and a `Fingerprint`, a 128-bit hash value the exact meaning of which //! specifies the kind of thing it represents, like a piece of HIR, MIR, etc.)
//! and a [`Fingerprint`], a 128-bit hash value, the exact meaning of which
//! depends on the node's `DepKind`. Together, the kind and the fingerprint //! depends on the node's `DepKind`. Together, the kind and the fingerprint
//! fully identify a dependency node, even across multiple compilation sessions. //! fully identify a dependency node, even across multiple compilation sessions.
//! In other words, the value of the fingerprint does not depend on anything //! In other words, the value of the fingerprint does not depend on anything
//! that is specific to a given compilation session, like an unpredictable //! that is specific to a given compilation session, like an unpredictable
//! interning key (e.g., NodeId, DefId, Symbol) or the numeric value of a //! interning key (e.g., `NodeId`, `DefId`, `Symbol`) or the numeric value of a
//! pointer. The concept behind this could be compared to how git commit hashes //! pointer. The concept behind this could be compared to how git commit hashes
//! uniquely identify a given commit and has a few advantages: //! uniquely identify a given commit. The fingerprinting approach has
//! a few advantages:
//! //!
//! * A `DepNode` can simply be serialized to disk and loaded in another session //! * A `DepNode` can simply be serialized to disk and loaded in another session
//! without the need to do any "rebasing" (like we have to do for Spans and //! without the need to do any "rebasing" (like we have to do for Spans and
@ -51,6 +52,8 @@
//! than a zeroed out fingerprint. More generally speaking, it relieves the //! than a zeroed out fingerprint. More generally speaking, it relieves the
//! user of the `DepNode` API of having to know how to compute the expected //! user of the `DepNode` API of having to know how to compute the expected
//! fingerprint for a given set of node parameters. //! fingerprint for a given set of node parameters.
//!
//! [dependency graph]: https://rustc-dev-guide.rust-lang.org/query.html
use crate::ty::TyCtxt; use crate::ty::TyCtxt;

View File

@ -127,6 +127,8 @@ pub enum InvalidProgramInfo<'tcx> {
Layout(layout::LayoutError<'tcx>), Layout(layout::LayoutError<'tcx>),
/// An invalid transmute happened. /// An invalid transmute happened.
TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>), TransmuteSizeDiff(Ty<'tcx>, Ty<'tcx>),
/// SizeOf of unsized type was requested.
SizeOfUnsizedType(Ty<'tcx>),
} }
impl fmt::Display for InvalidProgramInfo<'_> { impl fmt::Display for InvalidProgramInfo<'_> {
@ -144,6 +146,7 @@ impl fmt::Display for InvalidProgramInfo<'_> {
"transmuting `{}` to `{}` is not possible, because these types do not have the same size", "transmuting `{}` to `{}` is not possible, because these types do not have the same size",
from_ty, to_ty from_ty, to_ty
), ),
SizeOfUnsizedType(ty) => write!(f, "size_of called on unsized type `{}`", ty),
} }
} }
} }

View File

@ -289,7 +289,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
); );
} }
let ty = PlaceRef::ty(&used_place, self.body, self.infcx.tcx).ty; let ty = used_place.ty(self.body, self.infcx.tcx).ty;
let needs_note = match ty.kind() { let needs_note = match ty.kind() {
ty::Closure(id, _) => { ty::Closure(id, _) => {
let tables = self.infcx.tcx.typeck(id.expect_local()); let tables = self.infcx.tcx.typeck(id.expect_local());
@ -728,6 +728,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// Define a small closure that we can use to check if the type of a place // Define a small closure that we can use to check if the type of a place
// is a union. // is a union.
let union_ty = |place_base| { let union_ty = |place_base| {
// Need to use fn call syntax `PlaceRef::ty` to determine the type of `place_base`;
// using a type annotation in the closure argument instead leads to a lifetime error.
let ty = PlaceRef::ty(&place_base, self.body, self.infcx.tcx).ty; let ty = PlaceRef::ty(&place_base, self.body, self.infcx.tcx).ty;
ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty) ty.ty_adt_def().filter(|adt| adt.is_union()).map(|_| ty)
}; };

View File

@ -1743,7 +1743,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
if let Some((place_base, ProjectionElem::Subslice { from, to, from_end: false })) = if let Some((place_base, ProjectionElem::Subslice { from, to, from_end: false })) =
place_span.0.last_projection() place_span.0.last_projection()
{ {
let place_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx); let place_ty = place_base.ty(self.body(), self.infcx.tcx);
if let ty::Array(..) = place_ty.ty.kind() { if let ty::Array(..) = place_ty.ty.kind() {
self.check_if_subslice_element_is_moved( self.check_if_subslice_element_is_moved(
location, location,
@ -1854,7 +1854,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// assigning to `P.f` requires `P` itself // assigning to `P.f` requires `P` itself
// be already initialized // be already initialized
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
let base_ty = PlaceRef::ty(&place_base, self.body(), tcx).ty; let base_ty = place_base.ty(self.body(), tcx).ty;
match base_ty.kind() { match base_ty.kind() {
ty::Adt(def, _) if def.has_dtor(tcx) => { ty::Adt(def, _) if def.has_dtor(tcx) => {
self.check_if_path_or_subpath_is_moved( self.check_if_path_or_subpath_is_moved(
@ -1951,7 +1951,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// no move out from an earlier location) then this is an attempt at initialization // no move out from an earlier location) then this is an attempt at initialization
// of the union - we should error in that case. // of the union - we should error in that case.
let tcx = this.infcx.tcx; let tcx = this.infcx.tcx;
if let ty::Adt(def, _) = PlaceRef::ty(&base, this.body(), tcx).ty.kind() { if let ty::Adt(def, _) = base.ty(this.body(), tcx).ty.kind() {
if def.is_union() { if def.is_union() {
if this.move_data.path_map[mpi].iter().any(|moi| { if this.move_data.path_map[mpi].iter().any(|moi| {
this.move_data.moves[*moi].source.is_predecessor_of(location, this.body) this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
@ -2173,7 +2173,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
Some((place_base, elem)) => { Some((place_base, elem)) => {
match elem { match elem {
ProjectionElem::Deref => { ProjectionElem::Deref => {
let base_ty = PlaceRef::ty(&place_base, self.body(), self.infcx.tcx).ty; let base_ty = place_base.ty(self.body(), self.infcx.tcx).ty;
// Check the kind of deref to decide // Check the kind of deref to decide
match base_ty.kind() { match base_ty.kind() {

View File

@ -117,7 +117,7 @@ impl<'cx, 'tcx> Iterator for Prefixes<'cx, 'tcx> {
// derefs, except we stop at the deref of a shared // derefs, except we stop at the deref of a shared
// reference. // reference.
let ty = PlaceRef::ty(&cursor_base, self.body, self.tcx).ty; let ty = cursor_base.ty(self.body, self.tcx).ty;
match ty.kind() { match ty.kind() {
ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => { ty::RawPtr(_) | ty::Ref(_ /*rgn*/, _ /*ty*/, hir::Mutability::Not) => {
// don't continue traversing over derefs of raw pointers or shared // don't continue traversing over derefs of raw pointers or shared

View File

@ -270,6 +270,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
self.frame().current_span(), self.frame().current_span(),
&format!("SizeOf nullary MIR operator called for unsized type {}", ty), &format!("SizeOf nullary MIR operator called for unsized type {}", ty),
); );
throw_inval!(SizeOfUnsizedType(ty));
} }
self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), dest)?; self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), dest)?;
} }

View File

@ -1465,16 +1465,14 @@ impl<'a> Resolver<'a> {
/// Entry point to crate resolution. /// Entry point to crate resolution.
pub fn resolve_crate(&mut self, krate: &Crate) { pub fn resolve_crate(&mut self, krate: &Crate) {
let _prof_timer = self.session.prof.generic_activity("resolve_crate"); self.session.time("resolve_crate", || {
self.session.time("finalize_imports", || ImportResolver { r: self }.finalize_imports());
ImportResolver { r: self }.finalize_imports(); self.session.time("finalize_macro_resolutions", || self.finalize_macro_resolutions());
self.finalize_macro_resolutions(); self.session.time("late_resolve_crate", || self.late_resolve_crate(krate));
self.session.time("resolve_check_unused", || self.check_unused(krate));
self.late_resolve_crate(krate); self.session.time("resolve_report_errors", || self.report_errors(krate));
self.session.time("resolve_postprocess", || self.crate_loader.postprocess(krate));
self.check_unused(krate); });
self.report_errors(krate);
self.crate_loader.postprocess(krate);
} }
pub fn traits_in_scope( pub fn traits_in_scope(

View File

@ -66,7 +66,7 @@ pub(super) fn check_fn<'a, 'tcx>(
// Create the function context. This is either derived from scratch or, // Create the function context. This is either derived from scratch or,
// in the case of closures, based on the outer context. // in the case of closures, based on the outer context.
let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id); let mut fcx = FnCtxt::new(inherited, param_env, body.value.hir_id);
*fcx.ps.borrow_mut() = UnsafetyState::function(fn_sig.unsafety, fn_id); fcx.ps.set(UnsafetyState::function(fn_sig.unsafety, fn_id));
let tcx = fcx.tcx; let tcx = fcx.tcx;
let sess = tcx.sess; let sess = tcx.sess;

View File

@ -1472,22 +1472,22 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
fn_output = Some(&fn_decl.output); // `impl Trait` return type fn_output = Some(&fn_decl.output); // `impl Trait` return type
} }
} }
if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.borrow().as_ref(), fn_output) { if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) {
self.add_impl_trait_explanation(&mut err, cause, fcx, expected, *sp, fn_output); self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output);
} }
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() { if let Some(sp) = fcx.ret_coercion_span.get() {
// If the closure has an explicit return type annotation, // If the closure has an explicit return type annotation,
// then a type error may occur at the first return expression we // then a type error may occur at the first return expression we
// see in the closure (if it conflicts with the declared // see in the closure (if it conflicts with the declared
// return type). Skip adding a note in this case, since it // return type). Skip adding a note in this case, since it
// would be incorrect. // would be incorrect.
if !err.span.primary_spans().iter().any(|span| span == sp) { if !err.span.primary_spans().iter().any(|&span| span == sp) {
let hir = fcx.tcx.hir(); let hir = fcx.tcx.hir();
let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id)); let body_owner = hir.body_owned_by(hir.enclosing_body_owner(fcx.body_id));
if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) { if fcx.tcx.is_closure(hir.body_owner_def_id(body_owner).to_def_id()) {
err.span_note( err.span_note(
*sp, sp,
&format!( &format!(
"return type inferred to be `{}` here", "return type inferred to be `{}` here",
fcx.resolve_vars_if_possible(expected) fcx.resolve_vars_if_possible(expected)

View File

@ -680,14 +680,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.ret_coercion.is_none() { if self.ret_coercion.is_none() {
self.tcx.sess.emit_err(ReturnStmtOutsideOfFnBody { span: expr.span }); self.tcx.sess.emit_err(ReturnStmtOutsideOfFnBody { span: expr.span });
} else if let Some(ref e) = expr_opt { } else if let Some(ref e) = expr_opt {
if self.ret_coercion_span.borrow().is_none() { if self.ret_coercion_span.get().is_none() {
*self.ret_coercion_span.borrow_mut() = Some(e.span); self.ret_coercion_span.set(Some(e.span));
} }
self.check_return_expr(e); self.check_return_expr(e);
} else { } else {
let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut(); let mut coercion = self.ret_coercion.as_ref().unwrap().borrow_mut();
if self.ret_coercion_span.borrow().is_none() { if self.ret_coercion_span.get().is_none() {
*self.ret_coercion_span.borrow_mut() = Some(expr.span); self.ret_coercion_span.set(Some(expr.span));
} }
let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression); let cause = self.cause(expr.span, ObligationCauseCode::ReturnNoExpression);
if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) { if let Some((fn_decl, _)) = self.get_fn_decl(expr.hir_id) {

View File

@ -23,7 +23,6 @@ use rustc_span::{self, MultiSpan, Span};
use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression}; use rustc_trait_selection::traits::{self, ObligationCauseCode, StatementAsExpression};
use crate::structured_errors::StructuredDiagnostic; use crate::structured_errors::StructuredDiagnostic;
use std::mem::replace;
use std::slice; use std::slice;
impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@ -589,11 +588,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
blk: &'tcx hir::Block<'tcx>, blk: &'tcx hir::Block<'tcx>,
expected: Expectation<'tcx>, expected: Expectation<'tcx>,
) -> Ty<'tcx> { ) -> Ty<'tcx> {
let prev = { let prev = self.ps.replace(self.ps.get().recurse(blk));
let mut fcx_ps = self.ps.borrow_mut();
let unsafety_state = fcx_ps.recurse(blk);
replace(&mut *fcx_ps, unsafety_state)
};
// In some cases, blocks have just one exit, but other blocks // In some cases, blocks have just one exit, but other blocks
// can be targeted by multiple breaks. This can happen both // can be targeted by multiple breaks. This can happen both
@ -709,7 +704,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.write_ty(blk.hir_id, ty); self.write_ty(blk.hir_id, ty);
*self.ps.borrow_mut() = prev; self.ps.set(prev);
ty ty
} }

View File

@ -66,11 +66,11 @@ pub struct FnCtxt<'a, 'tcx> {
pub(super) in_tail_expr: bool, pub(super) in_tail_expr: bool,
/// First span of a return site that we find. Used in error messages. /// First span of a return site that we find. Used in error messages.
pub(super) ret_coercion_span: RefCell<Option<Span>>, pub(super) ret_coercion_span: Cell<Option<Span>>,
pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>, pub(super) resume_yield_tys: Option<(Ty<'tcx>, Ty<'tcx>)>,
pub(super) ps: RefCell<UnsafetyState>, pub(super) ps: Cell<UnsafetyState>,
/// Whether the last checked node generates a divergence (e.g., /// Whether the last checked node generates a divergence (e.g.,
/// `return` will set this to `Always`). In general, when entering /// `return` will set this to `Always`). In general, when entering
@ -127,9 +127,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ret_coercion_impl_trait: None, ret_coercion_impl_trait: None,
ret_type_span: None, ret_type_span: None,
in_tail_expr: false, in_tail_expr: false,
ret_coercion_span: RefCell::new(None), ret_coercion_span: Cell::new(None),
resume_yield_tys: None, resume_yield_tys: None,
ps: RefCell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)), ps: Cell::new(UnsafetyState::function(hir::Unsafety::Normal, hir::CRATE_HIR_ID)),
diverges: Cell::new(Diverges::Maybe), diverges: Cell::new(Diverges::Maybe),
has_errors: Cell::new(false), has_errors: Cell::new(false),
enclosing_breakables: RefCell::new(EnclosingBreakables { enclosing_breakables: RefCell::new(EnclosingBreakables {

View File

@ -184,14 +184,14 @@ impl UnsafetyState {
UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true } UnsafetyState { def, unsafety, unsafe_push_count: 0, from_fn: true }
} }
pub fn recurse(&mut self, blk: &hir::Block<'_>) -> UnsafetyState { pub fn recurse(self, blk: &hir::Block<'_>) -> UnsafetyState {
use hir::BlockCheckMode; use hir::BlockCheckMode;
match self.unsafety { match self.unsafety {
// If this unsafe, then if the outer function was already marked as // If this unsafe, then if the outer function was already marked as
// unsafe we shouldn't attribute the unsafe'ness to the block. This // unsafe we shouldn't attribute the unsafe'ness to the block. This
// way the block can be warned about instead of ignoring this // way the block can be warned about instead of ignoring this
// extraneous block (functions are never warned about). // extraneous block (functions are never warned about).
hir::Unsafety::Unsafe if self.from_fn => *self, hir::Unsafety::Unsafe if self.from_fn => self,
unsafety => { unsafety => {
let (unsafety, def, count) = match blk.rules { let (unsafety, def, count) = match blk.rules {

View File

@ -2646,9 +2646,13 @@ impl<A: Ord> Ord for VecDeque<A> {
impl<A: Hash> Hash for VecDeque<A> { impl<A: Hash> Hash for VecDeque<A> {
fn hash<H: Hasher>(&self, state: &mut H) { fn hash<H: Hasher>(&self, state: &mut H) {
self.len().hash(state); self.len().hash(state);
let (a, b) = self.as_slices(); // It's not possible to use Hash::hash_slice on slices
Hash::hash_slice(a, state); // returned by as_slices method as their length can vary
Hash::hash_slice(b, state); // in otherwise identical deques.
//
// Hasher only guarantees equivalence for the exact same
// set of calls to its methods.
self.iter().for_each(|elem| elem.hash(state));
} }
} }

View File

@ -599,3 +599,43 @@ fn issue_53529() {
assert_eq!(*a, 2); assert_eq!(*a, 2);
} }
} }
#[test]
fn issue_80303() {
use core::iter;
use core::num::Wrapping;
// This is a valid, albeit rather bad hash function implementation.
struct SimpleHasher(Wrapping<u64>);
impl Hasher for SimpleHasher {
fn finish(&self) -> u64 {
self.0.0
}
fn write(&mut self, bytes: &[u8]) {
// This particular implementation hashes value 24 in addition to bytes.
// Such an implementation is valid as Hasher only guarantees equivalence
// for the exact same set of calls to its methods.
for &v in iter::once(&24).chain(bytes) {
self.0 = Wrapping(31) * self.0 + Wrapping(u64::from(v));
}
}
}
fn hash_code(value: impl Hash) -> u64 {
let mut hasher = SimpleHasher(Wrapping(1));
value.hash(&mut hasher);
hasher.finish()
}
// This creates two deques for which values returned by as_slices
// method differ.
let vda: VecDeque<u8> = (0..10).collect();
let mut vdb = VecDeque::with_capacity(10);
vdb.extend(5..10);
(0..5).rev().for_each(|elem| vdb.push_front(elem));
assert_ne!(vda.as_slices(), vdb.as_slices());
assert_eq!(vda, vdb);
assert_eq!(hash_code(vda), hash_code(vdb));
}

View File

@ -3,7 +3,7 @@
//! # Problem statement //! # Problem statement
//! //!
//! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`), //! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`),
//! fractional (`45`), and exponent (`56`) parts. All parts are optional and interpreted as zero //! fractional (`34`), and exponent (`56`) parts. All parts are optional and interpreted as zero
//! when missing. //! when missing.
//! //!
//! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal //! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal

View File

@ -19,12 +19,19 @@ use crate::slice::{self, SliceIndex};
/// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`. /// as a discriminant -- `Option<NonNull<T>>` has the same size as `*mut T`.
/// However the pointer may still dangle if it isn't dereferenced. /// However the pointer may still dangle if it isn't dereferenced.
/// ///
/// Unlike `*mut T`, `NonNull<T>` is covariant over `T`. If this is incorrect /// Unlike `*mut T`, `NonNull<T>` was chosen to be covariant over `T`. This makes it
/// for your use case, you should include some [`PhantomData`] in your type to /// possible to use `NonNull<T>` when building covariant types, but introduces the
/// provide invariance, such as `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`. /// risk of unsoundness if used in a type that shouldn't actually be covariant.
/// Usually this won't be necessary; covariance is correct for most safe abstractions, /// (The opposite choice was made for `*mut T` even though technically the unsoundness
/// such as `Box`, `Rc`, `Arc`, `Vec`, and `LinkedList`. This is the case because they /// could only be caused by calling unsafe functions.)
/// provide a public API that follows the normal shared XOR mutable rules of Rust. ///
/// Covariance is correct for most safe abstractions, such as `Box`, `Rc`, `Arc`, `Vec`,
/// and `LinkedList`. This is the case because they provide a public API that follows the
/// normal shared XOR mutable rules of Rust.
///
/// If your type cannot safely be covariant, you must ensure it contains some
/// additional field to provide invariance. Often this field will be a [`PhantomData`]
/// type like `PhantomData<Cell<T>>` or `PhantomData<&'a mut T>`.
/// ///
/// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does /// Notice that `NonNull<T>` has a `From` instance for `&T`. However, this does
/// not change the fact that mutating through a (pointer derived from a) shared /// not change the fact that mutating through a (pointer derived from a) shared

View File

@ -111,6 +111,7 @@ impl OsString {
/// let os_string = OsString::new(); /// let os_string = OsString::new();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn new() -> OsString { pub fn new() -> OsString {
OsString { inner: Buf::from_string(String::new()) } OsString { inner: Buf::from_string(String::new()) }
} }
@ -127,6 +128,7 @@ impl OsString {
/// assert_eq!(os_string.as_os_str(), os_str); /// assert_eq!(os_string.as_os_str(), os_str);
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn as_os_str(&self) -> &OsStr { pub fn as_os_str(&self) -> &OsStr {
self self
} }
@ -145,6 +147,7 @@ impl OsString {
/// assert_eq!(string, Ok(String::from("foo"))); /// assert_eq!(string, Ok(String::from("foo")));
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn into_string(self) -> Result<String, OsString> { pub fn into_string(self) -> Result<String, OsString> {
self.inner.into_string().map_err(|buf| OsString { inner: buf }) self.inner.into_string().map_err(|buf| OsString { inner: buf })
} }
@ -163,6 +166,7 @@ impl OsString {
/// assert_eq!(&os_string, "foobar"); /// assert_eq!(&os_string, "foobar");
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn push<T: AsRef<OsStr>>(&mut self, s: T) { pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
self.inner.push_slice(&s.as_ref().inner) self.inner.push_slice(&s.as_ref().inner)
} }
@ -189,6 +193,7 @@ impl OsString {
/// assert_eq!(capacity, os_string.capacity()); /// assert_eq!(capacity, os_string.capacity());
/// ``` /// ```
#[stable(feature = "osstring_simple_functions", since = "1.9.0")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
#[inline]
pub fn with_capacity(capacity: usize) -> OsString { pub fn with_capacity(capacity: usize) -> OsString {
OsString { inner: Buf::with_capacity(capacity) } OsString { inner: Buf::with_capacity(capacity) }
} }
@ -207,6 +212,7 @@ impl OsString {
/// assert_eq!(&os_string, ""); /// assert_eq!(&os_string, "");
/// ``` /// ```
#[stable(feature = "osstring_simple_functions", since = "1.9.0")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
#[inline]
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.inner.clear() self.inner.clear()
} }
@ -224,6 +230,7 @@ impl OsString {
/// assert!(os_string.capacity() >= 10); /// assert!(os_string.capacity() >= 10);
/// ``` /// ```
#[stable(feature = "osstring_simple_functions", since = "1.9.0")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
#[inline]
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
self.inner.capacity() self.inner.capacity()
} }
@ -243,6 +250,7 @@ impl OsString {
/// assert!(s.capacity() >= 10); /// assert!(s.capacity() >= 10);
/// ``` /// ```
#[stable(feature = "osstring_simple_functions", since = "1.9.0")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
#[inline]
pub fn reserve(&mut self, additional: usize) { pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional) self.inner.reserve(additional)
} }
@ -265,6 +273,7 @@ impl OsString {
/// assert!(s.capacity() >= 10); /// assert!(s.capacity() >= 10);
/// ``` /// ```
#[stable(feature = "osstring_simple_functions", since = "1.9.0")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
#[inline]
pub fn reserve_exact(&mut self, additional: usize) { pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional) self.inner.reserve_exact(additional)
} }
@ -285,6 +294,7 @@ impl OsString {
/// assert_eq!(3, s.capacity()); /// assert_eq!(3, s.capacity());
/// ``` /// ```
#[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")] #[stable(feature = "osstring_shrink_to_fit", since = "1.19.0")]
#[inline]
pub fn shrink_to_fit(&mut self) { pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit() self.inner.shrink_to_fit()
} }
@ -342,6 +352,7 @@ impl From<String> for OsString {
/// Converts a [`String`] into a [`OsString`]. /// Converts a [`String`] into a [`OsString`].
/// ///
/// The conversion copies the data, and includes an allocation on the heap. /// The conversion copies the data, and includes an allocation on the heap.
#[inline]
fn from(s: String) -> OsString { fn from(s: String) -> OsString {
OsString { inner: Buf::from_string(s) } OsString { inner: Buf::from_string(s) }
} }
@ -408,6 +419,7 @@ impl fmt::Debug for OsString {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq for OsString { impl PartialEq for OsString {
#[inline]
fn eq(&self, other: &OsString) -> bool { fn eq(&self, other: &OsString) -> bool {
&**self == &**other &**self == &**other
} }
@ -415,6 +427,7 @@ impl PartialEq for OsString {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<str> for OsString { impl PartialEq<str> for OsString {
#[inline]
fn eq(&self, other: &str) -> bool { fn eq(&self, other: &str) -> bool {
&**self == other &**self == other
} }
@ -422,6 +435,7 @@ impl PartialEq<str> for OsString {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl PartialEq<OsString> for str { impl PartialEq<OsString> for str {
#[inline]
fn eq(&self, other: &OsString) -> bool { fn eq(&self, other: &OsString) -> bool {
&**other == self &**other == self
} }
@ -429,6 +443,7 @@ impl PartialEq<OsString> for str {
#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")] #[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
impl PartialEq<&str> for OsString { impl PartialEq<&str> for OsString {
#[inline]
fn eq(&self, other: &&str) -> bool { fn eq(&self, other: &&str) -> bool {
**self == **other **self == **other
} }
@ -436,6 +451,7 @@ impl PartialEq<&str> for OsString {
#[stable(feature = "os_str_str_ref_eq", since = "1.29.0")] #[stable(feature = "os_str_str_ref_eq", since = "1.29.0")]
impl<'a> PartialEq<OsString> for &'a str { impl<'a> PartialEq<OsString> for &'a str {
#[inline]
fn eq(&self, other: &OsString) -> bool { fn eq(&self, other: &OsString) -> bool {
**other == **self **other == **self
} }
@ -539,6 +555,7 @@ impl OsStr {
/// assert_eq!(os_str.to_str(), Some("foo")); /// assert_eq!(os_str.to_str(), Some("foo"));
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_str(&self) -> Option<&str> { pub fn to_str(&self) -> Option<&str> {
self.inner.to_str() self.inner.to_str()
} }
@ -589,6 +606,7 @@ impl OsStr {
/// } /// }
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_string_lossy(&self) -> Cow<'_, str> { pub fn to_string_lossy(&self) -> Cow<'_, str> {
self.inner.to_string_lossy() self.inner.to_string_lossy()
} }
@ -605,6 +623,7 @@ impl OsStr {
/// assert_eq!(os_string, OsString::from("foo")); /// assert_eq!(os_string, OsString::from("foo"));
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_os_string(&self) -> OsString { pub fn to_os_string(&self) -> OsString {
OsString { inner: self.inner.to_owned() } OsString { inner: self.inner.to_owned() }
} }
@ -655,6 +674,7 @@ impl OsStr {
/// ``` /// ```
#[doc(alias = "length")] #[doc(alias = "length")]
#[stable(feature = "osstring_simple_functions", since = "1.9.0")] #[stable(feature = "osstring_simple_functions", since = "1.9.0")]
#[inline]
pub fn len(&self) -> usize { pub fn len(&self) -> usize {
self.inner.inner.len() self.inner.inner.len()
} }
@ -696,6 +716,7 @@ impl OsStr {
/// assert_eq!("grÜße, jÜrgen ❤", s); /// assert_eq!("grÜße, jÜrgen ❤", s);
/// ``` /// ```
#[unstable(feature = "osstring_ascii", issue = "70516")] #[unstable(feature = "osstring_ascii", issue = "70516")]
#[inline]
pub fn make_ascii_lowercase(&mut self) { pub fn make_ascii_lowercase(&mut self) {
self.inner.make_ascii_lowercase() self.inner.make_ascii_lowercase()
} }
@ -721,6 +742,7 @@ impl OsStr {
/// assert_eq!("GRüßE, JüRGEN ❤", s); /// assert_eq!("GRüßE, JüRGEN ❤", s);
/// ``` /// ```
#[unstable(feature = "osstring_ascii", issue = "70516")] #[unstable(feature = "osstring_ascii", issue = "70516")]
#[inline]
pub fn make_ascii_uppercase(&mut self) { pub fn make_ascii_uppercase(&mut self) {
self.inner.make_ascii_uppercase() self.inner.make_ascii_uppercase()
} }
@ -784,6 +806,7 @@ impl OsStr {
/// assert!(!non_ascii.is_ascii()); /// assert!(!non_ascii.is_ascii());
/// ``` /// ```
#[unstable(feature = "osstring_ascii", issue = "70516")] #[unstable(feature = "osstring_ascii", issue = "70516")]
#[inline]
pub fn is_ascii(&self) -> bool { pub fn is_ascii(&self) -> bool {
self.inner.is_ascii() self.inner.is_ascii()
} }
@ -811,6 +834,7 @@ impl OsStr {
#[stable(feature = "box_from_os_str", since = "1.17.0")] #[stable(feature = "box_from_os_str", since = "1.17.0")]
impl From<&OsStr> for Box<OsStr> { impl From<&OsStr> for Box<OsStr> {
#[inline]
fn from(s: &OsStr) -> Box<OsStr> { fn from(s: &OsStr) -> Box<OsStr> {
let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr; let rw = Box::into_raw(s.inner.into_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) } unsafe { Box::from_raw(rw) }
@ -832,6 +856,7 @@ impl From<Cow<'_, OsStr>> for Box<OsStr> {
impl From<Box<OsStr>> for OsString { impl From<Box<OsStr>> for OsString {
/// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or /// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or
/// allocating. /// allocating.
#[inline]
fn from(boxed: Box<OsStr>) -> OsString { fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string() boxed.into_os_string()
} }
@ -840,6 +865,7 @@ impl From<Box<OsStr>> for OsString {
#[stable(feature = "box_from_os_string", since = "1.20.0")] #[stable(feature = "box_from_os_string", since = "1.20.0")]
impl From<OsString> for Box<OsStr> { impl From<OsString> for Box<OsStr> {
/// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating. /// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
#[inline]
fn from(s: OsString) -> Box<OsStr> { fn from(s: OsString) -> Box<OsStr> {
s.into_boxed_os_str() s.into_boxed_os_str()
} }
@ -925,6 +951,7 @@ impl<'a> From<Cow<'a, OsStr>> for OsString {
#[stable(feature = "box_default_extra", since = "1.17.0")] #[stable(feature = "box_default_extra", since = "1.17.0")]
impl Default for Box<OsStr> { impl Default for Box<OsStr> {
#[inline]
fn default() -> Box<OsStr> { fn default() -> Box<OsStr> {
let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr; let rw = Box::into_raw(Slice::empty_box()) as *mut OsStr;
unsafe { Box::from_raw(rw) } unsafe { Box::from_raw(rw) }
@ -1075,6 +1102,7 @@ impl OsStr {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<OsStr> for OsString { impl Borrow<OsStr> for OsString {
#[inline]
fn borrow(&self) -> &OsStr { fn borrow(&self) -> &OsStr {
&self[..] &self[..]
} }
@ -1083,9 +1111,11 @@ impl Borrow<OsStr> for OsString {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for OsStr { impl ToOwned for OsStr {
type Owned = OsString; type Owned = OsString;
#[inline]
fn to_owned(&self) -> OsString { fn to_owned(&self) -> OsString {
self.to_os_string() self.to_os_string()
} }
#[inline]
fn clone_into(&self, target: &mut OsString) { fn clone_into(&self, target: &mut OsString) {
self.inner.clone_into(&mut target.inner) self.inner.clone_into(&mut target.inner)
} }
@ -1093,6 +1123,7 @@ impl ToOwned for OsStr {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for OsStr { impl AsRef<OsStr> for OsStr {
#[inline]
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
self self
} }
@ -1123,12 +1154,14 @@ impl AsRef<OsStr> for String {
} }
impl FromInner<Buf> for OsString { impl FromInner<Buf> for OsString {
#[inline]
fn from_inner(buf: Buf) -> OsString { fn from_inner(buf: Buf) -> OsString {
OsString { inner: buf } OsString { inner: buf }
} }
} }
impl IntoInner<Buf> for OsString { impl IntoInner<Buf> for OsString {
#[inline]
fn into_inner(self) -> Buf { fn into_inner(self) -> Buf {
self.inner self.inner
} }
@ -1145,6 +1178,7 @@ impl AsInner<Slice> for OsStr {
impl FromStr for OsString { impl FromStr for OsString {
type Err = core::convert::Infallible; type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(OsString::from(s)) Ok(OsString::from(s))
} }

View File

@ -401,12 +401,14 @@ impl<'a> PrefixComponent<'a> {
/// See [`Prefix`]'s documentation for more information on the different /// See [`Prefix`]'s documentation for more information on the different
/// kinds of prefixes. /// kinds of prefixes.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn kind(&self) -> Prefix<'a> { pub fn kind(&self) -> Prefix<'a> {
self.parsed self.parsed
} }
/// Returns the raw [`OsStr`] slice for this prefix. /// Returns the raw [`OsStr`] slice for this prefix.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn as_os_str(&self) -> &'a OsStr { pub fn as_os_str(&self) -> &'a OsStr {
self.raw self.raw
} }
@ -414,6 +416,7 @@ impl<'a> PrefixComponent<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialEq for PrefixComponent<'a> { impl<'a> cmp::PartialEq for PrefixComponent<'a> {
#[inline]
fn eq(&self, other: &PrefixComponent<'a>) -> bool { fn eq(&self, other: &PrefixComponent<'a>) -> bool {
cmp::PartialEq::eq(&self.parsed, &other.parsed) cmp::PartialEq::eq(&self.parsed, &other.parsed)
} }
@ -421,6 +424,7 @@ impl<'a> cmp::PartialEq for PrefixComponent<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialOrd for PrefixComponent<'a> { impl<'a> cmp::PartialOrd for PrefixComponent<'a> {
#[inline]
fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &PrefixComponent<'a>) -> Option<cmp::Ordering> {
cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed) cmp::PartialOrd::partial_cmp(&self.parsed, &other.parsed)
} }
@ -428,6 +432,7 @@ impl<'a> cmp::PartialOrd for PrefixComponent<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Ord for PrefixComponent<'_> { impl cmp::Ord for PrefixComponent<'_> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering { fn cmp(&self, other: &Self) -> cmp::Ordering {
cmp::Ord::cmp(&self.parsed, &other.parsed) cmp::Ord::cmp(&self.parsed, &other.parsed)
} }
@ -522,6 +527,7 @@ impl<'a> Component<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for Component<'_> { impl AsRef<OsStr> for Component<'_> {
#[inline]
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
self.as_os_str() self.as_os_str()
} }
@ -529,6 +535,7 @@ impl AsRef<OsStr> for Component<'_> {
#[stable(feature = "path_component_asref", since = "1.25.0")] #[stable(feature = "path_component_asref", since = "1.25.0")]
impl AsRef<Path> for Component<'_> { impl AsRef<Path> for Component<'_> {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
self.as_os_str().as_ref() self.as_os_str().as_ref()
} }
@ -750,6 +757,7 @@ impl<'a> Components<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for Components<'_> { impl AsRef<Path> for Components<'_> {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
self.as_path() self.as_path()
} }
@ -757,6 +765,7 @@ impl AsRef<Path> for Components<'_> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for Components<'_> { impl AsRef<OsStr> for Components<'_> {
#[inline]
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
self.as_path().as_os_str() self.as_path().as_os_str()
} }
@ -792,6 +801,7 @@ impl<'a> Iter<'a> {
/// assert_eq!(Path::new("foo/bar.txt"), iter.as_path()); /// assert_eq!(Path::new("foo/bar.txt"), iter.as_path());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn as_path(&self) -> &'a Path { pub fn as_path(&self) -> &'a Path {
self.inner.as_path() self.inner.as_path()
} }
@ -799,6 +809,7 @@ impl<'a> Iter<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for Iter<'_> { impl AsRef<Path> for Iter<'_> {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
self.as_path() self.as_path()
} }
@ -806,6 +817,7 @@ impl AsRef<Path> for Iter<'_> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for Iter<'_> { impl AsRef<OsStr> for Iter<'_> {
#[inline]
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
self.as_path().as_os_str() self.as_path().as_os_str()
} }
@ -815,6 +827,7 @@ impl AsRef<OsStr> for Iter<'_> {
impl<'a> Iterator for Iter<'a> { impl<'a> Iterator for Iter<'a> {
type Item = &'a OsStr; type Item = &'a OsStr;
#[inline]
fn next(&mut self) -> Option<&'a OsStr> { fn next(&mut self) -> Option<&'a OsStr> {
self.inner.next().map(Component::as_os_str) self.inner.next().map(Component::as_os_str)
} }
@ -822,6 +835,7 @@ impl<'a> Iterator for Iter<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a> DoubleEndedIterator for Iter<'a> { impl<'a> DoubleEndedIterator for Iter<'a> {
#[inline]
fn next_back(&mut self) -> Option<&'a OsStr> { fn next_back(&mut self) -> Option<&'a OsStr> {
self.inner.next_back().map(Component::as_os_str) self.inner.next_back().map(Component::as_os_str)
} }
@ -935,6 +949,7 @@ impl FusedIterator for Components<'_> {}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialEq for Components<'a> { impl<'a> cmp::PartialEq for Components<'a> {
#[inline]
fn eq(&self, other: &Components<'a>) -> bool { fn eq(&self, other: &Components<'a>) -> bool {
Iterator::eq(self.clone(), other.clone()) Iterator::eq(self.clone(), other.clone())
} }
@ -945,6 +960,7 @@ impl cmp::Eq for Components<'_> {}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a> cmp::PartialOrd for Components<'a> { impl<'a> cmp::PartialOrd for Components<'a> {
#[inline]
fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &Components<'a>) -> Option<cmp::Ordering> {
Iterator::partial_cmp(self.clone(), other.clone()) Iterator::partial_cmp(self.clone(), other.clone())
} }
@ -952,6 +968,7 @@ impl<'a> cmp::PartialOrd for Components<'a> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Ord for Components<'_> { impl cmp::Ord for Components<'_> {
#[inline]
fn cmp(&self, other: &Self) -> cmp::Ordering { fn cmp(&self, other: &Self) -> cmp::Ordering {
Iterator::cmp(self.clone(), other.clone()) Iterator::cmp(self.clone(), other.clone())
} }
@ -985,6 +1002,7 @@ pub struct Ancestors<'a> {
impl<'a> Iterator for Ancestors<'a> { impl<'a> Iterator for Ancestors<'a> {
type Item = &'a Path; type Item = &'a Path;
#[inline]
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
let next = self.next; let next = self.next;
self.next = next.and_then(Path::parent); self.next = next.and_then(Path::parent);
@ -1060,6 +1078,7 @@ pub struct PathBuf {
} }
impl PathBuf { impl PathBuf {
#[inline]
fn as_mut_vec(&mut self) -> &mut Vec<u8> { fn as_mut_vec(&mut self) -> &mut Vec<u8> {
unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) } unsafe { &mut *(self as *mut PathBuf as *mut Vec<u8>) }
} }
@ -1074,6 +1093,7 @@ impl PathBuf {
/// let path = PathBuf::new(); /// let path = PathBuf::new();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn new() -> PathBuf { pub fn new() -> PathBuf {
PathBuf { inner: OsString::new() } PathBuf { inner: OsString::new() }
} }
@ -1097,6 +1117,7 @@ impl PathBuf {
/// ///
/// [`with_capacity`]: OsString::with_capacity /// [`with_capacity`]: OsString::with_capacity
#[stable(feature = "path_buf_capacity", since = "1.44.0")] #[stable(feature = "path_buf_capacity", since = "1.44.0")]
#[inline]
pub fn with_capacity(capacity: usize) -> PathBuf { pub fn with_capacity(capacity: usize) -> PathBuf {
PathBuf { inner: OsString::with_capacity(capacity) } PathBuf { inner: OsString::with_capacity(capacity) }
} }
@ -1112,6 +1133,7 @@ impl PathBuf {
/// assert_eq!(Path::new("/test"), p.as_path()); /// assert_eq!(Path::new("/test"), p.as_path());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn as_path(&self) -> &Path { pub fn as_path(&self) -> &Path {
self self
} }
@ -1315,12 +1337,14 @@ impl PathBuf {
/// let os_str = p.into_os_string(); /// let os_str = p.into_os_string();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn into_os_string(self) -> OsString { pub fn into_os_string(self) -> OsString {
self.inner self.inner
} }
/// Converts this `PathBuf` into a [boxed](Box) [`Path`]. /// Converts this `PathBuf` into a [boxed](Box) [`Path`].
#[stable(feature = "into_boxed_path", since = "1.20.0")] #[stable(feature = "into_boxed_path", since = "1.20.0")]
#[inline]
pub fn into_boxed_path(self) -> Box<Path> { pub fn into_boxed_path(self) -> Box<Path> {
let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path; let rw = Box::into_raw(self.inner.into_boxed_os_str()) as *mut Path;
unsafe { Box::from_raw(rw) } unsafe { Box::from_raw(rw) }
@ -1330,6 +1354,7 @@ impl PathBuf {
/// ///
/// [`capacity`]: OsString::capacity /// [`capacity`]: OsString::capacity
#[stable(feature = "path_buf_capacity", since = "1.44.0")] #[stable(feature = "path_buf_capacity", since = "1.44.0")]
#[inline]
pub fn capacity(&self) -> usize { pub fn capacity(&self) -> usize {
self.inner.capacity() self.inner.capacity()
} }
@ -1338,6 +1363,7 @@ impl PathBuf {
/// ///
/// [`clear`]: OsString::clear /// [`clear`]: OsString::clear
#[stable(feature = "path_buf_capacity", since = "1.44.0")] #[stable(feature = "path_buf_capacity", since = "1.44.0")]
#[inline]
pub fn clear(&mut self) { pub fn clear(&mut self) {
self.inner.clear() self.inner.clear()
} }
@ -1346,6 +1372,7 @@ impl PathBuf {
/// ///
/// [`reserve`]: OsString::reserve /// [`reserve`]: OsString::reserve
#[stable(feature = "path_buf_capacity", since = "1.44.0")] #[stable(feature = "path_buf_capacity", since = "1.44.0")]
#[inline]
pub fn reserve(&mut self, additional: usize) { pub fn reserve(&mut self, additional: usize) {
self.inner.reserve(additional) self.inner.reserve(additional)
} }
@ -1354,6 +1381,7 @@ impl PathBuf {
/// ///
/// [`reserve_exact`]: OsString::reserve_exact /// [`reserve_exact`]: OsString::reserve_exact
#[stable(feature = "path_buf_capacity", since = "1.44.0")] #[stable(feature = "path_buf_capacity", since = "1.44.0")]
#[inline]
pub fn reserve_exact(&mut self, additional: usize) { pub fn reserve_exact(&mut self, additional: usize) {
self.inner.reserve_exact(additional) self.inner.reserve_exact(additional)
} }
@ -1362,6 +1390,7 @@ impl PathBuf {
/// ///
/// [`shrink_to_fit`]: OsString::shrink_to_fit /// [`shrink_to_fit`]: OsString::shrink_to_fit
#[stable(feature = "path_buf_capacity", since = "1.44.0")] #[stable(feature = "path_buf_capacity", since = "1.44.0")]
#[inline]
pub fn shrink_to_fit(&mut self) { pub fn shrink_to_fit(&mut self) {
self.inner.shrink_to_fit() self.inner.shrink_to_fit()
} }
@ -1370,6 +1399,7 @@ impl PathBuf {
/// ///
/// [`shrink_to`]: OsString::shrink_to /// [`shrink_to`]: OsString::shrink_to
#[unstable(feature = "shrink_to", issue = "56431")] #[unstable(feature = "shrink_to", issue = "56431")]
#[inline]
pub fn shrink_to(&mut self, min_capacity: usize) { pub fn shrink_to(&mut self, min_capacity: usize) {
self.inner.shrink_to(min_capacity) self.inner.shrink_to(min_capacity)
} }
@ -1400,6 +1430,7 @@ impl From<Box<Path>> for PathBuf {
/// Converts a `Box<Path>` into a `PathBuf` /// Converts a `Box<Path>` into a `PathBuf`
/// ///
/// This conversion does not allocate or copy memory. /// This conversion does not allocate or copy memory.
#[inline]
fn from(boxed: Box<Path>) -> PathBuf { fn from(boxed: Box<Path>) -> PathBuf {
boxed.into_path_buf() boxed.into_path_buf()
} }
@ -1411,6 +1442,7 @@ impl From<PathBuf> for Box<Path> {
/// ///
/// This conversion currently should not allocate memory, /// This conversion currently should not allocate memory,
/// but this behavior is not guaranteed on all platforms or in all future versions. /// but this behavior is not guaranteed on all platforms or in all future versions.
#[inline]
fn from(p: PathBuf) -> Box<Path> { fn from(p: PathBuf) -> Box<Path> {
p.into_boxed_path() p.into_boxed_path()
} }
@ -1426,6 +1458,7 @@ impl Clone for Box<Path> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf { impl<T: ?Sized + AsRef<OsStr>> From<&T> for PathBuf {
#[inline]
fn from(s: &T) -> PathBuf { fn from(s: &T) -> PathBuf {
PathBuf::from(s.as_ref().to_os_string()) PathBuf::from(s.as_ref().to_os_string())
} }
@ -1447,6 +1480,7 @@ impl From<PathBuf> for OsString {
/// Converts a `PathBuf` into a `OsString` /// Converts a `PathBuf` into a `OsString`
/// ///
/// This conversion does not allocate or copy memory. /// This conversion does not allocate or copy memory.
#[inline]
fn from(path_buf: PathBuf) -> OsString { fn from(path_buf: PathBuf) -> OsString {
path_buf.inner path_buf.inner
} }
@ -1457,6 +1491,7 @@ impl From<String> for PathBuf {
/// Converts a `String` into a `PathBuf` /// Converts a `String` into a `PathBuf`
/// ///
/// This conversion does not allocate or copy memory. /// This conversion does not allocate or copy memory.
#[inline]
fn from(s: String) -> PathBuf { fn from(s: String) -> PathBuf {
PathBuf::from(OsString::from(s)) PathBuf::from(OsString::from(s))
} }
@ -1466,6 +1501,7 @@ impl From<String> for PathBuf {
impl FromStr for PathBuf { impl FromStr for PathBuf {
type Err = core::convert::Infallible; type Err = core::convert::Infallible;
#[inline]
fn from_str(s: &str) -> Result<Self, Self::Err> { fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(PathBuf::from(s)) Ok(PathBuf::from(s))
} }
@ -1510,6 +1546,7 @@ impl ops::Deref for PathBuf {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl Borrow<Path> for PathBuf { impl Borrow<Path> for PathBuf {
#[inline]
fn borrow(&self) -> &Path { fn borrow(&self) -> &Path {
self.deref() self.deref()
} }
@ -1517,6 +1554,7 @@ impl Borrow<Path> for PathBuf {
#[stable(feature = "default_for_pathbuf", since = "1.17.0")] #[stable(feature = "default_for_pathbuf", since = "1.17.0")]
impl Default for PathBuf { impl Default for PathBuf {
#[inline]
fn default() -> Self { fn default() -> Self {
PathBuf::new() PathBuf::new()
} }
@ -1597,9 +1635,11 @@ impl From<&Path> for Rc<Path> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl ToOwned for Path { impl ToOwned for Path {
type Owned = PathBuf; type Owned = PathBuf;
#[inline]
fn to_owned(&self) -> PathBuf { fn to_owned(&self) -> PathBuf {
self.to_path_buf() self.to_path_buf()
} }
#[inline]
fn clone_into(&self, target: &mut PathBuf) { fn clone_into(&self, target: &mut PathBuf) {
self.inner.clone_into(&mut target.inner); self.inner.clone_into(&mut target.inner);
} }
@ -1607,6 +1647,7 @@ impl ToOwned for Path {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialEq for PathBuf { impl cmp::PartialEq for PathBuf {
#[inline]
fn eq(&self, other: &PathBuf) -> bool { fn eq(&self, other: &PathBuf) -> bool {
self.components() == other.components() self.components() == other.components()
} }
@ -1624,6 +1665,7 @@ impl cmp::Eq for PathBuf {}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialOrd for PathBuf { impl cmp::PartialOrd for PathBuf {
#[inline]
fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &PathBuf) -> Option<cmp::Ordering> {
self.components().partial_cmp(other.components()) self.components().partial_cmp(other.components())
} }
@ -1631,6 +1673,7 @@ impl cmp::PartialOrd for PathBuf {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Ord for PathBuf { impl cmp::Ord for PathBuf {
#[inline]
fn cmp(&self, other: &PathBuf) -> cmp::Ordering { fn cmp(&self, other: &PathBuf) -> cmp::Ordering {
self.components().cmp(other.components()) self.components().cmp(other.components())
} }
@ -1638,6 +1681,7 @@ impl cmp::Ord for PathBuf {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for PathBuf { impl AsRef<OsStr> for PathBuf {
#[inline]
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
&self.inner[..] &self.inner[..]
} }
@ -1745,6 +1789,7 @@ impl Path {
/// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt")); /// assert_eq!(os_str, std::ffi::OsStr::new("foo.txt"));
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn as_os_str(&self) -> &OsStr { pub fn as_os_str(&self) -> &OsStr {
&self.inner &self.inner
} }
@ -1766,6 +1811,7 @@ impl Path {
/// assert_eq!(path.to_str(), Some("foo.txt")); /// assert_eq!(path.to_str(), Some("foo.txt"));
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_str(&self) -> Option<&str> { pub fn to_str(&self) -> Option<&str> {
self.inner.to_str() self.inner.to_str()
} }
@ -1791,6 +1837,7 @@ impl Path {
/// Had `path` contained invalid unicode, the `to_string_lossy` call might /// Had `path` contained invalid unicode, the `to_string_lossy` call might
/// have returned `"fo<66>.txt"`. /// have returned `"fo<66>.txt"`.
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn to_string_lossy(&self) -> Cow<'_, str> { pub fn to_string_lossy(&self) -> Cow<'_, str> {
self.inner.to_string_lossy() self.inner.to_string_lossy()
} }
@ -1854,6 +1901,7 @@ impl Path {
/// ///
/// [`is_absolute`]: Path::is_absolute /// [`is_absolute`]: Path::is_absolute
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_relative(&self) -> bool { pub fn is_relative(&self) -> bool {
!self.is_absolute() !self.is_absolute()
} }
@ -1879,6 +1927,7 @@ impl Path {
/// assert!(Path::new("/etc/passwd").has_root()); /// assert!(Path::new("/etc/passwd").has_root());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn has_root(&self) -> bool { pub fn has_root(&self) -> bool {
self.components().has_root() self.components().has_root()
} }
@ -1941,6 +1990,7 @@ impl Path {
/// ///
/// [`parent`]: Path::parent /// [`parent`]: Path::parent
#[stable(feature = "path_ancestors", since = "1.28.0")] #[stable(feature = "path_ancestors", since = "1.28.0")]
#[inline]
pub fn ancestors(&self) -> Ancestors<'_> { pub fn ancestors(&self) -> Ancestors<'_> {
Ancestors { next: Some(&self) } Ancestors { next: Some(&self) }
} }
@ -2265,6 +2315,7 @@ impl Path {
/// assert_eq!(it.next(), None) /// assert_eq!(it.next(), None)
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn iter(&self) -> Iter<'_> { pub fn iter(&self) -> Iter<'_> {
Iter { inner: self.components() } Iter { inner: self.components() }
} }
@ -2284,6 +2335,7 @@ impl Path {
/// println!("{}", path.display()); /// println!("{}", path.display());
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn display(&self) -> Display<'_> { pub fn display(&self) -> Display<'_> {
Display { path: self } Display { path: self }
} }
@ -2305,6 +2357,7 @@ impl Path {
/// println!("{:?}", metadata.file_type()); /// println!("{:?}", metadata.file_type());
/// ``` /// ```
#[stable(feature = "path_ext", since = "1.5.0")] #[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn metadata(&self) -> io::Result<fs::Metadata> { pub fn metadata(&self) -> io::Result<fs::Metadata> {
fs::metadata(self) fs::metadata(self)
} }
@ -2323,6 +2376,7 @@ impl Path {
/// println!("{:?}", metadata.file_type()); /// println!("{:?}", metadata.file_type());
/// ``` /// ```
#[stable(feature = "path_ext", since = "1.5.0")] #[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> { pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
fs::symlink_metadata(self) fs::symlink_metadata(self)
} }
@ -2341,6 +2395,7 @@ impl Path {
/// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs")); /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
/// ``` /// ```
#[stable(feature = "path_ext", since = "1.5.0")] #[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn canonicalize(&self) -> io::Result<PathBuf> { pub fn canonicalize(&self) -> io::Result<PathBuf> {
fs::canonicalize(self) fs::canonicalize(self)
} }
@ -2358,6 +2413,7 @@ impl Path {
/// let path_link = path.read_link().expect("read_link call failed"); /// let path_link = path.read_link().expect("read_link call failed");
/// ``` /// ```
#[stable(feature = "path_ext", since = "1.5.0")] #[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn read_link(&self) -> io::Result<PathBuf> { pub fn read_link(&self) -> io::Result<PathBuf> {
fs::read_link(self) fs::read_link(self)
} }
@ -2382,6 +2438,7 @@ impl Path {
/// } /// }
/// ``` /// ```
#[stable(feature = "path_ext", since = "1.5.0")] #[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn read_dir(&self) -> io::Result<fs::ReadDir> { pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
fs::read_dir(self) fs::read_dir(self)
} }
@ -2406,6 +2463,7 @@ impl Path {
/// This is a convenience function that coerces errors to false. If you want to /// This is a convenience function that coerces errors to false. If you want to
/// check errors, call [`fs::metadata`]. /// check errors, call [`fs::metadata`].
#[stable(feature = "path_ext", since = "1.5.0")] #[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn exists(&self) -> bool { pub fn exists(&self) -> bool {
fs::metadata(self).is_ok() fs::metadata(self).is_ok()
} }
@ -2480,6 +2538,7 @@ impl Path {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<OsStr> for Path { impl AsRef<OsStr> for Path {
#[inline]
fn as_ref(&self) -> &OsStr { fn as_ref(&self) -> &OsStr {
&self.inner &self.inner
} }
@ -2531,6 +2590,7 @@ impl fmt::Display for Display<'_> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialEq for Path { impl cmp::PartialEq for Path {
#[inline]
fn eq(&self, other: &Path) -> bool { fn eq(&self, other: &Path) -> bool {
self.components().eq(other.components()) self.components().eq(other.components())
} }
@ -2550,6 +2610,7 @@ impl cmp::Eq for Path {}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::PartialOrd for Path { impl cmp::PartialOrd for Path {
#[inline]
fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> { fn partial_cmp(&self, other: &Path) -> Option<cmp::Ordering> {
self.components().partial_cmp(other.components()) self.components().partial_cmp(other.components())
} }
@ -2557,6 +2618,7 @@ impl cmp::PartialOrd for Path {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl cmp::Ord for Path { impl cmp::Ord for Path {
#[inline]
fn cmp(&self, other: &Path) -> cmp::Ordering { fn cmp(&self, other: &Path) -> cmp::Ordering {
self.components().cmp(other.components()) self.components().cmp(other.components())
} }
@ -2564,6 +2626,7 @@ impl cmp::Ord for Path {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for Path { impl AsRef<Path> for Path {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
self self
} }
@ -2571,6 +2634,7 @@ impl AsRef<Path> for Path {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for OsStr { impl AsRef<Path> for OsStr {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
Path::new(self) Path::new(self)
} }
@ -2578,6 +2642,7 @@ impl AsRef<Path> for OsStr {
#[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")] #[stable(feature = "cow_os_str_as_ref_path", since = "1.8.0")]
impl AsRef<Path> for Cow<'_, OsStr> { impl AsRef<Path> for Cow<'_, OsStr> {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
Path::new(self) Path::new(self)
} }
@ -2585,6 +2650,7 @@ impl AsRef<Path> for Cow<'_, OsStr> {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for OsString { impl AsRef<Path> for OsString {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
Path::new(self) Path::new(self)
} }
@ -2600,6 +2666,7 @@ impl AsRef<Path> for str {
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<Path> for String { impl AsRef<Path> for String {
#[inline]
fn as_ref(&self) -> &Path { fn as_ref(&self) -> &Path {
Path::new(self) Path::new(self)
} }
@ -2617,6 +2684,7 @@ impl AsRef<Path> for PathBuf {
impl<'a> IntoIterator for &'a PathBuf { impl<'a> IntoIterator for &'a PathBuf {
type Item = &'a OsStr; type Item = &'a OsStr;
type IntoIter = Iter<'a>; type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Iter<'a> { fn into_iter(self) -> Iter<'a> {
self.iter() self.iter()
} }
@ -2626,6 +2694,7 @@ impl<'a> IntoIterator for &'a PathBuf {
impl<'a> IntoIterator for &'a Path { impl<'a> IntoIterator for &'a Path {
type Item = &'a OsStr; type Item = &'a OsStr;
type IntoIter = Iter<'a>; type IntoIter = Iter<'a>;
#[inline]
fn into_iter(self) -> Iter<'a> { fn into_iter(self) -> Iter<'a> {
self.iter() self.iter()
} }

View File

@ -1096,7 +1096,10 @@ impl Clean<Item> for hir::TraitItem<'_> {
AssocTypeItem(bounds.clean(cx), default.clean(cx)) AssocTypeItem(bounds.clean(cx), default.clean(cx))
} }
}; };
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx) let what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
// Trait items always inherit the trait's visibility -- we don't want to show `pub`.
Item { visibility: Inherited, ..what_rustc_thinks }
}) })
} }
} }
@ -1131,7 +1134,21 @@ impl Clean<Item> for hir::ImplItem<'_> {
) )
} }
}; };
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx)
let what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(self.hir_id));
if let hir::ItemKind::Impl(impl_) = &parent_item.kind {
if impl_.of_trait.is_some() {
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
Item { visibility: Inherited, ..what_rustc_thinks }
} else {
what_rustc_thinks
}
} else {
panic!("found impl item with non-impl parent {:?}", parent_item);
}
}) })
} }
} }

View File

@ -12,6 +12,9 @@ use crate::formats::cache::{Cache, CACHE_KEY};
/// backend renderer has hooks for initialization, documenting an item, entering and exiting a /// backend renderer has hooks for initialization, documenting an item, entering and exiting a
/// module, and cleanup/finalizing output. /// module, and cleanup/finalizing output.
crate trait FormatRenderer<'tcx>: Clone { crate trait FormatRenderer<'tcx>: Clone {
/// Gives a description of the renderer. Used for performance profiling.
fn descr() -> &'static str;
/// Sets up any state required for the renderer. When this is called the cache has already been /// Sets up any state required for the renderer. When this is called the cache has already been
/// populated. /// populated.
fn init( fn init(
@ -57,16 +60,20 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
edition: Edition, edition: Edition,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let (krate, mut cache) = Cache::from_krate( let (krate, mut cache) = tcx.sess.time("create_format_cache", || {
render_info.clone(), Cache::from_krate(
options.document_private, render_info.clone(),
&options.extern_html_root_urls, options.document_private,
&options.output, &options.extern_html_root_urls,
krate, &options.output,
); krate,
)
});
let prof = &tcx.sess.prof;
let (mut format_renderer, mut krate) = let (mut format_renderer, mut krate) = prof
T::init(krate, options, render_info, edition, &mut cache, tcx)?; .extra_verbose_generic_activity("create_renderer", T::descr())
.run(|| T::init(krate, options, render_info, edition, &mut cache, tcx))?;
let cache = Arc::new(cache); let cache = Arc::new(cache);
// Freeze the cache now that the index has been built. Put an Arc into TLS for future // Freeze the cache now that the index has been built. Put an Arc into TLS for future
@ -83,6 +90,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
// Render the crate documentation // Render the crate documentation
let mut work = vec![(format_renderer.clone(), item)]; let mut work = vec![(format_renderer.clone(), item)];
let unknown = rustc_span::Symbol::intern("<unknown item>");
while let Some((mut cx, item)) = work.pop() { while let Some((mut cx, item)) = work.pop() {
if item.is_mod() { if item.is_mod() {
// modules are special because they add a namespace. We also need to // modules are special because they add a namespace. We also need to
@ -91,6 +99,7 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
if name.is_empty() { if name.is_empty() {
panic!("Unexpected module with empty name"); panic!("Unexpected module with empty name");
} }
let _timer = prof.generic_activity_with_arg("render_mod_item", name.as_str());
cx.mod_item_in(&item, &name, &cache)?; cx.mod_item_in(&item, &name, &cache)?;
let module = match *item.kind { let module = match *item.kind {
@ -104,9 +113,10 @@ crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
cx.mod_item_out(&name)?; cx.mod_item_out(&name)?;
} else if item.name.is_some() { } else if item.name.is_some() {
cx.item(item, &cache)?; prof.generic_activity_with_arg("render_item", &*item.name.unwrap_or(unknown).as_str())
.run(|| cx.item(item, &cache))?;
} }
} }
prof.extra_verbose_generic_activity("renderer_after_krate", T::descr())
format_renderer.after_krate(&krate, &cache, diag) .run(|| format_renderer.after_krate(&krate, &cache, diag))
} }

View File

@ -383,6 +383,10 @@ crate fn initial_ids() -> Vec<String> {
/// Generates the documentation for `crate` into the directory `dst` /// Generates the documentation for `crate` into the directory `dst`
impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
fn descr() -> &'static str {
"html"
}
fn init( fn init(
mut krate: clean::Crate, mut krate: clean::Crate,
options: RenderOptions, options: RenderOptions,

View File

@ -125,6 +125,10 @@ impl JsonRenderer<'_> {
} }
impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> { impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
fn descr() -> &'static str {
"json"
}
fn init( fn init(
krate: clean::Crate, krate: clean::Crate,
options: RenderOptions, options: RenderOptions,

View File

@ -540,7 +540,7 @@ fn main_options(options: config::Options) -> MainResult {
sess.fatal("Compilation failed, aborting rustdoc"); sess.fatal("Compilation failed, aborting rustdoc");
} }
let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).peek_mut();
global_ctxt.enter(|tcx| { global_ctxt.enter(|tcx| {
let (mut krate, render_info, render_opts) = sess.time("run_global_ctxt", || { let (mut krate, render_info, render_opts) = sess.time("run_global_ctxt", || {

View File

@ -42,3 +42,35 @@ mod a {
struct FooBPriv; struct FooBPriv;
} }
} }
// @has 'foo/trait.PubTrait.html' '//pre' 'pub trait PubTrait'
//
// @has 'foo/trait.PubTrait.html' '//pre' 'type Type;'
// @!has 'foo/trait.PubTrait.html' '//pre' 'pub type Type;'
//
// @has 'foo/trait.PubTrait.html' '//pre' 'const CONST: usize;'
// @!has 'foo/trait.PubTrait.html' '//pre' 'pub const CONST: usize;'
//
// @has 'foo/trait.PubTrait.html' '//pre' 'fn function();'
// @!has 'foo/trait.PubTrait.html' '//pre' 'pub fn function();'
pub trait PubTrait {
type Type;
const CONST: usize;
fn function();
}
// @has 'foo/struct.FooPublic.html' '//code' 'type Type'
// @!has 'foo/struct.FooPublic.html' '//code' 'pub type Type'
//
// @has 'foo/struct.FooPublic.html' '//code' 'const CONST: usize'
// @!has 'foo/struct.FooPublic.html' '//code' 'pub const CONST: usize'
//
// @has 'foo/struct.FooPublic.html' '//code' 'fn function()'
// @!has 'foo/struct.FooPublic.html' '//code' 'pub fn function()'
impl PubTrait for FooPublic {
type Type = usize;
const CONST: usize = 0;
fn function() {}
}

View File

@ -0,0 +1,17 @@
// Check that using the parameter name in its type does not ICE.
// edition:2018
#![feature(async_closure)]
fn main() {
let _ = |x: x| x; //~ ERROR expected type
let _ = |x: bool| -> x { x }; //~ ERROR expected type
let _ = async move |x: x| x; //~ ERROR expected type
let _ = async move |x: bool| -> x { x }; //~ ERROR expected type
}
fn foo(x: x) {} //~ ERROR expected type
fn foo_ret(x: bool) -> x {} //~ ERROR expected type
async fn async_foo(x: x) {} //~ ERROR expected type
async fn async_foo_ret(x: bool) -> x {} //~ ERROR expected type

View File

@ -0,0 +1,51 @@
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:7:17
|
LL | let _ = |x: x| x;
| ^ not a type
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:8:26
|
LL | let _ = |x: bool| -> x { x };
| ^ not a type
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:9:28
|
LL | let _ = async move |x: x| x;
| ^ not a type
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:10:37
|
LL | let _ = async move |x: bool| -> x { x };
| ^ not a type
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:13:11
|
LL | fn foo(x: x) {}
| ^ not a type
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:14:24
|
LL | fn foo_ret(x: bool) -> x {}
| ^ not a type
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:16:23
|
LL | async fn async_foo(x: x) {}
| ^ not a type
error[E0573]: expected type, found local variable `x`
--> $DIR/local-type-mix.rs:17:36
|
LL | async fn async_foo_ret(x: bool) -> x {}
| ^ not a type
error: aborting due to 8 previous errors
For more information about this error, try `rustc --explain E0573`.

View File

@ -1,3 +1,17 @@
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| size_of called on unsized type `dyn Debug`
| inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
::: $DIR/issue-80742.rs:23:10
|
LL | [u8; size_of::<T>() + 1]: ,
| -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:23:10
error[E0599]: no function or associated item named `new` found for struct `Inline<dyn Debug>` in the current scope error[E0599]: no function or associated item named `new` found for struct `Inline<dyn Debug>` in the current scope
--> $DIR/issue-80742.rs:31:36 --> $DIR/issue-80742.rs:31:36
| |
@ -21,6 +35,20 @@ LL | pub trait Debug {
= note: the method `new` exists but the following trait bounds were not satisfied: = note: the method `new` exists but the following trait bounds were not satisfied:
`dyn Debug: Sized` `dyn Debug: Sized`
error[E0080]: evaluation of constant value failed
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
LL | intrinsics::size_of::<T>()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| size_of called on unsized type `dyn Debug`
| inside `std::mem::size_of::<dyn Debug>` at $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
::: $DIR/issue-80742.rs:15:10
|
LL | [u8; size_of::<T>() + 1]: ,
| -------------- inside `Inline::<dyn Debug>::{constant#0}` at $DIR/issue-80742.rs:15:10
error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time error[E0277]: the size for values of type `dyn Debug` cannot be known at compilation time
--> $DIR/issue-80742.rs:31:15 --> $DIR/issue-80742.rs:31:15
| |
@ -36,7 +64,7 @@ help: consider relaxing the implicit `Sized` restriction
LL | struct Inline<T: ?Sized> LL | struct Inline<T: ?Sized>
| ^^^^^^^^ | ^^^^^^^^
error: aborting due to 2 previous errors error: aborting due to 4 previous errors
Some errors have detailed explanations: E0277, E0599. Some errors have detailed explanations: E0080, E0277, E0599.
For more information about an error, try `rustc --explain E0277`. For more information about an error, try `rustc --explain E0080`.

@ -1 +1 @@
Subproject commit a73e5b7d567c3036b296fc6b33ed52c5edcd882e Subproject commit 783bc43c660bf39c1e562c8c429b32078ad3099b