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:
bors 2024-01-20 19:55:26 +00:00
commit 038d115cd8
49 changed files with 97 additions and 76 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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;

View File

@ -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.

View File

@ -37,6 +37,7 @@ static SETTINGS_HASHES: &[&str] = &[
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
];
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");

View File

@ -1,4 +1,5 @@
{
"git.detectSubmodulesLimit": 20,
"rust-analyzer.check.invocationLocation": "root",
"rust-analyzer.check.invocationStrategy": "once",
"rust-analyzer.check.overrideCommand": [

View File

@ -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;
}
}

View File

@ -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,

View File

@ -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)

View File

@ -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;

View File

@ -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> {}

View 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) {}
}