Auto merge of #120170 - GuillaumeGomez:rollup-edqdf30, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - #119997 (Fix impl stripped in rustdoc HTML whereas it should not be in case the impl is implemented on a type alias) - #120000 (Ensure `callee_id`s are body owners) - #120063 (Remove special handling of `box` expressions from parser) - #120116 (Remove alignment-changing in-place collect) - #120138 (Increase vscode settings.json `git.detectSubmodulesLimit`) - #120169 (Spelling fix) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
038d115cd8
@ -33,7 +33,6 @@ use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
|
||||
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
|
||||
use rustc_session::lint::BuiltinLintDiagnostics;
|
||||
use rustc_span::source_map::{self, Spanned};
|
||||
use rustc_span::symbol::kw::PathRoot;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::{BytePos, Pos, Span};
|
||||
use thin_vec::{thin_vec, ThinVec};
|
||||
@ -642,26 +641,13 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
/// Parse `box expr` - this syntax has been removed, but we still parse this
|
||||
/// for now to provide an automated way to fix usages of it
|
||||
fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
let (span, expr) = self.parse_expr_prefix_common(lo)?;
|
||||
let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap();
|
||||
self.dcx().emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() });
|
||||
// So typechecking works, parse `box <expr>` as `::std::boxed::Box::new(expr)`
|
||||
let path = Path {
|
||||
span,
|
||||
segments: [
|
||||
PathSegment::from_ident(Ident::with_dummy_span(PathRoot)),
|
||||
PathSegment::from_ident(Ident::with_dummy_span(sym::std)),
|
||||
PathSegment::from_ident(Ident::from_str("boxed")),
|
||||
PathSegment::from_ident(Ident::from_str("Box")),
|
||||
PathSegment::from_ident(Ident::with_dummy_span(sym::new)),
|
||||
]
|
||||
.into(),
|
||||
tokens: None,
|
||||
};
|
||||
let path = self.mk_expr(span, ExprKind::Path(None, path));
|
||||
Ok((span, self.mk_call(path, ThinVec::from([expr]))))
|
||||
/// for now to provide a more useful error
|
||||
fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
|
||||
let (span, _) = self.parse_expr_prefix_common(box_kw)?;
|
||||
let inner_span = span.with_lo(box_kw.hi());
|
||||
let code = self.sess.source_map().span_to_snippet(inner_span).unwrap();
|
||||
self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() });
|
||||
Ok((span, ExprKind::Err))
|
||||
}
|
||||
|
||||
fn is_mistaken_not_ident_negation(&self) -> bool {
|
||||
|
@ -168,7 +168,9 @@ const fn in_place_collectible<DEST, SRC>(
|
||||
step_merge: Option<NonZeroUsize>,
|
||||
step_expand: Option<NonZeroUsize>,
|
||||
) -> bool {
|
||||
if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::<SRC>() < mem::align_of::<DEST>() } {
|
||||
// Require matching alignments because an alignment-changing realloc is inefficient on many
|
||||
// system allocators and better implementations would require the unstable Allocator trait.
|
||||
if const { SRC::IS_ZST || DEST::IS_ZST || mem::align_of::<SRC>() != mem::align_of::<DEST>() } {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -188,7 +190,8 @@ const fn in_place_collectible<DEST, SRC>(
|
||||
|
||||
const fn needs_realloc<SRC, DEST>(src_cap: usize, dst_cap: usize) -> bool {
|
||||
if const { mem::align_of::<SRC>() != mem::align_of::<DEST>() } {
|
||||
return src_cap > 0;
|
||||
// FIXME: use unreachable! once that works in const
|
||||
panic!("in_place_collectible() prevents this");
|
||||
}
|
||||
|
||||
// If src type size is an integer multiple of the destination type size then
|
||||
@ -276,8 +279,8 @@ where
|
||||
let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap: dst_cap };
|
||||
src.forget_allocation_drop_remaining();
|
||||
|
||||
// Adjust the allocation if the alignment didn't match or the source had a capacity in bytes
|
||||
// that wasn't a multiple of the destination type size.
|
||||
// Adjust the allocation if the source had a capacity in bytes that wasn't a multiple
|
||||
// of the destination type size.
|
||||
// Since the discrepancy should generally be small this should only result in some
|
||||
// bookkeeping updates and no memmove.
|
||||
if needs_realloc::<I::Src, T>(src_cap, dst_cap) {
|
||||
@ -290,7 +293,7 @@ where
|
||||
let src_size = mem::size_of::<I::Src>().unchecked_mul(src_cap);
|
||||
let old_layout = Layout::from_size_align_unchecked(src_size, src_align);
|
||||
|
||||
// The must be equal or smaller for in-place iteration to be possible
|
||||
// The allocation must be equal or smaller for in-place iteration to be possible
|
||||
// therefore the new layout must be ≤ the old one and therefore valid.
|
||||
let dst_align = mem::align_of::<T>();
|
||||
let dst_size = mem::size_of::<T>().unchecked_mul(dst_cap);
|
||||
|
@ -13,13 +13,13 @@ use super::{IntoIter, SpecExtend, SpecFromIterNested, Vec};
|
||||
/// +-+-----------+
|
||||
/// |
|
||||
/// v
|
||||
/// +-+-------------------------------+ +---------------------+
|
||||
/// |SpecFromIter +---->+SpecFromIterNested |
|
||||
/// |where I: | | |where I: |
|
||||
/// | Iterator (default)----------+ | | Iterator (default) |
|
||||
/// | vec::IntoIter | | | TrustedLen |
|
||||
/// | SourceIterMarker---fallback-+ | +---------------------+
|
||||
/// +---------------------------------+
|
||||
/// +-+---------------------------------+ +---------------------+
|
||||
/// |SpecFromIter +---->+SpecFromIterNested |
|
||||
/// |where I: | | |where I: |
|
||||
/// | Iterator (default)------------+ | | Iterator (default) |
|
||||
/// | vec::IntoIter | | | TrustedLen |
|
||||
/// | InPlaceCollect--(fallback to)-+ | +---------------------+
|
||||
/// +-----------------------------------+
|
||||
/// ```
|
||||
pub(super) trait SpecFromIter<T, I> {
|
||||
fn from_iter(iter: I) -> Self;
|
||||
|
@ -415,7 +415,7 @@ where
|
||||
// Request and its methods
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// `Request` supports generic, type-driven access to data. It's use is currently restricted to the
|
||||
/// `Request` supports generic, type-driven access to data. Its use is currently restricted to the
|
||||
/// standard library in cases where trait authors wish to allow trait implementors to share generic
|
||||
/// information across trait boundaries. The motivating and prototypical use case is
|
||||
/// `core::error::Error` which would otherwise require a method per concrete type (eg.
|
||||
|
@ -37,6 +37,7 @@ static SETTINGS_HASHES: &[&str] = &[
|
||||
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
|
||||
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
|
||||
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
|
||||
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
|
||||
];
|
||||
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"git.detectSubmodulesLimit": 20,
|
||||
"rust-analyzer.check.invocationLocation": "root",
|
||||
"rust-analyzer.check.invocationStrategy": "once",
|
||||
"rust-analyzer.check.overrideCommand": [
|
||||
|
@ -56,13 +56,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
|
||||
| clean::TraitItem(..)
|
||||
| clean::FunctionItem(..)
|
||||
| clean::VariantItem(..)
|
||||
| clean::MethodItem(..)
|
||||
| clean::ForeignFunctionItem(..)
|
||||
| clean::ForeignStaticItem(..)
|
||||
| clean::ConstantItem(..)
|
||||
| clean::UnionItem(..)
|
||||
| clean::AssocConstItem(..)
|
||||
| clean::AssocTypeItem(..)
|
||||
| clean::TraitAliasItem(..)
|
||||
| clean::MacroItem(..)
|
||||
| clean::ForeignTypeItem => {
|
||||
@ -80,6 +77,16 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
|
||||
let item_id = i.item_id;
|
||||
if item_id.is_local()
|
||||
&& !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id())
|
||||
{
|
||||
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
clean::StructFieldItem(..) => {
|
||||
if i.visibility(self.tcx) != Some(Visibility::Public) {
|
||||
return Some(strip_item(i));
|
||||
@ -192,16 +199,16 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
|
||||
&& imp.items.iter().all(|i| {
|
||||
let item_id = i.item_id;
|
||||
item_id.is_local()
|
||||
&& !is_item_reachable(
|
||||
self.tcx,
|
||||
self.is_json_output,
|
||||
&self.cache.effective_visibilities,
|
||||
item_id,
|
||||
)
|
||||
&& !self
|
||||
.cache
|
||||
.effective_visibilities
|
||||
.is_reachable(self.tcx, item_id.expect_def_id())
|
||||
})
|
||||
{
|
||||
debug!("ImplStripper: no public item; removing {imp:?}");
|
||||
return None;
|
||||
} else if imp.items.is_empty() && i.doc_value().is_empty() {
|
||||
debug!("ImplStripper: no item and no doc; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
@ -212,13 +219,13 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
|
||||
&& !imp.for_.is_assoc_ty()
|
||||
&& !self.should_keep_impl(&i, did)
|
||||
{
|
||||
debug!("ImplStripper: impl item for stripped type; removing");
|
||||
debug!("ImplStripper: impl item for stripped type; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id())
|
||||
&& !self.should_keep_impl(&i, did)
|
||||
{
|
||||
debug!("ImplStripper: impl item for stripped trait; removing");
|
||||
debug!("ImplStripper: impl item for stripped trait; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
|
||||
@ -226,7 +233,7 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
|
||||
if let Some(did) = typaram.def_id(self.cache)
|
||||
&& !self.should_keep_impl(&i, did)
|
||||
{
|
||||
debug!("ImplStripper: stripped item in trait's generics; removing impl");
|
||||
debug!("ImplStripper: stripped item in trait's generics; removing {imp:?}");
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
@ -451,12 +451,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
|
||||
&& let Some(def_id) = trait_ref.trait_def_id()
|
||||
&& cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
|
||||
&& let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
|
||||
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[])
|
||||
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])
|
||||
// If all of our fields implement `Eq`, we can implement `Eq` too
|
||||
&& adt
|
||||
.all_fields()
|
||||
.map(|f| f.ty(cx.tcx, args))
|
||||
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[]))
|
||||
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]))
|
||||
{
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
|
@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>(
|
||||
.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
|
||||
&& let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
|
||||
&& let param_env = cx.tcx.param_env(fn_id)
|
||||
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[])
|
||||
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[])
|
||||
&& let Some(into_iter_ty) =
|
||||
make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty])
|
||||
&& let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)
|
||||
|
@ -214,36 +214,21 @@ pub fn implements_trait<'tcx>(
|
||||
trait_id: DefId,
|
||||
args: &[GenericArg<'tcx>],
|
||||
) -> bool {
|
||||
let callee_id = cx
|
||||
.enclosing_body
|
||||
.map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id());
|
||||
implements_trait_with_env_from_iter(
|
||||
cx.tcx,
|
||||
cx.param_env,
|
||||
ty,
|
||||
trait_id,
|
||||
callee_id,
|
||||
args.iter().map(|&x| Some(x)),
|
||||
)
|
||||
implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, None, args.iter().map(|&x| Some(x)))
|
||||
}
|
||||
|
||||
/// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
|
||||
///
|
||||
/// The `callee_id` argument is used to determine whether this is a function call in a `const fn` environment, used for checking const traits.
|
||||
pub fn implements_trait_with_env<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
param_env: ParamEnv<'tcx>,
|
||||
ty: Ty<'tcx>,
|
||||
trait_id: DefId,
|
||||
callee_id: DefId,
|
||||
callee_id: Option<DefId>,
|
||||
args: &[GenericArg<'tcx>],
|
||||
) -> bool {
|
||||
implements_trait_with_env_from_iter(
|
||||
tcx,
|
||||
param_env,
|
||||
ty,
|
||||
trait_id,
|
||||
Some(callee_id),
|
||||
args.iter().map(|&x| Some(x)),
|
||||
)
|
||||
implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x)))
|
||||
}
|
||||
|
||||
/// Same as `implements_trait_from_env` but takes the arguments as an iterator.
|
||||
@ -258,6 +243,13 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
|
||||
// Clippy shouldn't have infer types
|
||||
assert!(!ty.has_infer());
|
||||
|
||||
// If a `callee_id` is passed, then we assert that it is a body owner
|
||||
// through calling `body_owner_kind`, which would panic if the callee
|
||||
// does not have a body.
|
||||
if let Some(callee_id) = callee_id {
|
||||
let _ = tcx.hir().body_owner_kind(callee_id);
|
||||
}
|
||||
|
||||
let ty = tcx.erase_regions(ty);
|
||||
if ty.has_escaping_bound_vars() {
|
||||
return false;
|
||||
|
@ -48,6 +48,8 @@ impl Foo {
|
||||
|
||||
pub trait Pattern<'a> {}
|
||||
|
||||
impl Pattern<'_> for () {}
|
||||
|
||||
pub trait Trait<const N: usize> {}
|
||||
// @has async_fn/fn.const_generics.html
|
||||
// @has - '//pre[@class="rust item-decl"]' 'pub async fn const_generics<const N: usize>(_: impl Trait<N>)'
|
||||
@ -57,18 +59,18 @@ pub async fn const_generics<const N: usize>(_: impl Trait<N>) {}
|
||||
// regression test for #63037
|
||||
// @has async_fn/fn.elided.html
|
||||
// @has - '//pre[@class="rust item-decl"]' 'pub async fn elided(foo: &str) -> &str'
|
||||
pub async fn elided(foo: &str) -> &str {}
|
||||
pub async fn elided(foo: &str) -> &str { "" }
|
||||
// This should really be shown as written, but for implementation reasons it's difficult.
|
||||
// See `impl Clean for TyKind::Ref`.
|
||||
// @has async_fn/fn.user_elided.html
|
||||
// @has - '//pre[@class="rust item-decl"]' 'pub async fn user_elided(foo: &str) -> &str'
|
||||
pub async fn user_elided(foo: &'_ str) -> &str {}
|
||||
pub async fn user_elided(foo: &'_ str) -> &str { "" }
|
||||
// @has async_fn/fn.static_trait.html
|
||||
// @has - '//pre[@class="rust item-decl"]' 'pub async fn static_trait(foo: &str) -> Box<dyn Bar>'
|
||||
pub async fn static_trait(foo: &str) -> Box<dyn Bar> {}
|
||||
pub async fn static_trait(foo: &str) -> Box<dyn Bar> { Box::new(()) }
|
||||
// @has async_fn/fn.lifetime_for_trait.html
|
||||
// @has - '//pre[@class="rust item-decl"]' "pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_>"
|
||||
pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_> {}
|
||||
pub async fn lifetime_for_trait(foo: &str) -> Box<dyn Bar + '_> { Box::new(()) }
|
||||
// @has async_fn/fn.elided_in_input_trait.html
|
||||
// @has - '//pre[@class="rust item-decl"]' "pub async fn elided_in_input_trait(t: impl Pattern<'_>)"
|
||||
pub async fn elided_in_input_trait(t: impl Pattern<'_>) {}
|
||||
@ -78,10 +80,12 @@ struct AsyncFdReadyGuard<'a, T> { x: &'a T }
|
||||
impl Foo {
|
||||
// @has async_fn/struct.Foo.html
|
||||
// @has - '//*[@class="method"]' 'pub async fn complicated_lifetimes( &self, context: &impl Bar ) -> impl Iterator<Item = &usize>'
|
||||
pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {}
|
||||
pub async fn complicated_lifetimes(&self, context: &impl Bar) -> impl Iterator<Item = &usize> {
|
||||
[0].iter()
|
||||
}
|
||||
// taken from `tokio` as an example of a method that was particularly bad before
|
||||
// @has - '//*[@class="method"]' "pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()>"
|
||||
pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()> {}
|
||||
pub async fn readable<T>(&self) -> Result<AsyncFdReadyGuard<'_, T>, ()> { Err(()) }
|
||||
// @has - '//*[@class="method"]' "pub async fn mut_self(&mut self)"
|
||||
pub async fn mut_self(&mut self) {}
|
||||
}
|
||||
@ -89,7 +93,7 @@ impl Foo {
|
||||
// test named lifetimes, just in case
|
||||
// @has async_fn/fn.named.html
|
||||
// @has - '//pre[@class="rust item-decl"]' "pub async fn named<'a, 'b>(foo: &'a str) -> &'b str"
|
||||
pub async fn named<'a, 'b>(foo: &'a str) -> &'b str {}
|
||||
pub async fn named<'a, 'b>(foo: &'a str) -> &'b str { "" }
|
||||
// @has async_fn/fn.named_trait.html
|
||||
// @has - '//pre[@class="rust item-decl"]' "pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b>"
|
||||
pub async fn named_trait<'a, 'b>(foo: impl Pattern<'a>) -> impl Pattern<'b> {}
|
||||
|
27
tests/rustdoc/impl-on-ty-alias-issue-119015.rs
Normal file
27
tests/rustdoc/impl-on-ty-alias-issue-119015.rs
Normal file
@ -0,0 +1,27 @@
|
||||
#![crate_name = "foo"]
|
||||
|
||||
// @has 'foo/index.html'
|
||||
// There should be only `type A`.
|
||||
// @count - '//*[@class="item-table"]//*[@class="item-name"]' 1
|
||||
// @has - '//*[@class="item-name"]/a[@href="type.A.html"]' 'A'
|
||||
|
||||
mod foo {
|
||||
pub struct S;
|
||||
}
|
||||
|
||||
use foo::S;
|
||||
|
||||
pub type A = S;
|
||||
|
||||
// @has 'foo/type.A.html'
|
||||
// @has - '//*[@id="method.default"]/h4' 'fn default() -> Self'
|
||||
impl Default for A {
|
||||
fn default() -> Self {
|
||||
S
|
||||
}
|
||||
}
|
||||
|
||||
// @has - '//*[@id="method.a"]/h4' 'pub fn a(&self)'
|
||||
impl A {
|
||||
pub fn a(&self) {}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user