Skip to content

Commit e13d172

Browse files
committed
Auto merge of rust-lang#120163 - GuillaumeGomez:rollup-denmbz8, r=GuillaumeGomez
Rollup of 6 pull requests Successful merges: - rust-lang#118257 (Make traits / trait methods detected by the dead code lint) - rust-lang#119997 (Fix impl stripped in rustdoc HTML whereas it should not be in case the impl is implemented on a type alias) - rust-lang#120000 (Ensure `callee_id`s are body owners) - rust-lang#120015 (coverage: Format all coverage tests with `rustfmt`) - rust-lang#120063 (Remove special handling of `box` expressions from parser) - rust-lang#120138 (Increase vscode settings.json `git.detectSubmodulesLimit`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 159bdc1 + da2811e commit e13d172

File tree

386 files changed

+1530
-531
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

386 files changed

+1530
-531
lines changed

compiler/rustc_parse/src/parser/expr.rs

+7-21
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
3333
use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
3434
use rustc_session::lint::BuiltinLintDiagnostics;
3535
use rustc_span::source_map::{self, Spanned};
36-
use rustc_span::symbol::kw::PathRoot;
3736
use rustc_span::symbol::{kw, sym, Ident, Symbol};
3837
use rustc_span::{BytePos, Pos, Span};
3938
use thin_vec::{thin_vec, ThinVec};
@@ -642,26 +641,13 @@ impl<'a> Parser<'a> {
642641
}
643642

644643
/// Parse `box expr` - this syntax has been removed, but we still parse this
645-
/// for now to provide an automated way to fix usages of it
646-
fn parse_expr_box(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
647-
let (span, expr) = self.parse_expr_prefix_common(lo)?;
648-
let code = self.sess.source_map().span_to_snippet(span.with_lo(lo.hi())).unwrap();
649-
self.dcx().emit_err(errors::BoxSyntaxRemoved { span, code: code.trim() });
650-
// So typechecking works, parse `box <expr>` as `::std::boxed::Box::new(expr)`
651-
let path = Path {
652-
span,
653-
segments: [
654-
PathSegment::from_ident(Ident::with_dummy_span(PathRoot)),
655-
PathSegment::from_ident(Ident::with_dummy_span(sym::std)),
656-
PathSegment::from_ident(Ident::from_str("boxed")),
657-
PathSegment::from_ident(Ident::from_str("Box")),
658-
PathSegment::from_ident(Ident::with_dummy_span(sym::new)),
659-
]
660-
.into(),
661-
tokens: None,
662-
};
663-
let path = self.mk_expr(span, ExprKind::Path(None, path));
664-
Ok((span, self.mk_call(path, ThinVec::from([expr]))))
644+
/// for now to provide a more useful error
645+
fn parse_expr_box(&mut self, box_kw: Span) -> PResult<'a, (Span, ExprKind)> {
646+
let (span, _) = self.parse_expr_prefix_common(box_kw)?;
647+
let inner_span = span.with_lo(box_kw.hi());
648+
let code = self.sess.source_map().span_to_snippet(inner_span).unwrap();
649+
self.dcx().emit_err(errors::BoxSyntaxRemoved { span: span, code: code.trim() });
650+
Ok((span, ExprKind::Err))
665651
}
666652

667653
fn is_mistaken_not_ident_negation(&self) -> bool {

compiler/rustc_passes/src/dead.rs

+71-20
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// is dead.
55

66
use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
7+
use hir::ItemKind;
78
use rustc_data_structures::unord::UnordSet;
89
use rustc_errors::MultiSpan;
910
use rustc_hir as hir;
@@ -14,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
1415
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
1516
use rustc_middle::middle::privacy::Level;
1617
use rustc_middle::query::Providers;
17-
use rustc_middle::ty::{self, TyCtxt};
18+
use rustc_middle::ty::{self, TyCtxt, Visibility};
1819
use rustc_session::lint;
1920
use rustc_session::lint::builtin::DEAD_CODE;
2021
use rustc_span::symbol::{sym, Symbol};
@@ -381,9 +382,46 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
381382
intravisit::walk_item(self, item)
382383
}
383384
hir::ItemKind::ForeignMod { .. } => {}
385+
hir::ItemKind::Trait(..) => {
386+
for impl_def_id in self.tcx.all_impls(item.owner_id.to_def_id()) {
387+
if let Some(local_def_id) = impl_def_id.as_local()
388+
&& let ItemKind::Impl(impl_ref) =
389+
self.tcx.hir().expect_item(local_def_id).kind
390+
{
391+
// skip items
392+
// mark dependent traits live
393+
intravisit::walk_generics(self, impl_ref.generics);
394+
// mark dependent parameters live
395+
intravisit::walk_path(self, impl_ref.of_trait.unwrap().path);
396+
}
397+
}
398+
399+
intravisit::walk_item(self, item)
400+
}
384401
_ => intravisit::walk_item(self, item),
385402
},
386403
Node::TraitItem(trait_item) => {
404+
// mark corresponing ImplTerm live
405+
let trait_item_id = trait_item.owner_id.to_def_id();
406+
if let Some(trait_id) = self.tcx.trait_of_item(trait_item_id) {
407+
// mark the trait live
408+
self.check_def_id(trait_id);
409+
410+
for impl_id in self.tcx.all_impls(trait_id) {
411+
if let Some(local_impl_id) = impl_id.as_local()
412+
&& let ItemKind::Impl(impl_ref) =
413+
self.tcx.hir().expect_item(local_impl_id).kind
414+
{
415+
// mark self_ty live
416+
intravisit::walk_ty(self, impl_ref.self_ty);
417+
if let Some(&impl_item_id) =
418+
self.tcx.impl_item_implementor_ids(impl_id).get(&trait_item_id)
419+
{
420+
self.check_def_id(impl_item_id);
421+
}
422+
}
423+
}
424+
}
387425
intravisit::walk_trait_item(self, trait_item);
388426
}
389427
Node::ImplItem(impl_item) => {
@@ -632,10 +670,6 @@ fn check_item<'tcx>(
632670
}
633671
}
634672
DefKind::Impl { of_trait } => {
635-
if of_trait {
636-
worklist.push((id.owner_id.def_id, ComesFromAllowExpect::No));
637-
}
638-
639673
// get DefIds from another query
640674
let local_def_ids = tcx
641675
.associated_item_def_ids(id.owner_id)
@@ -644,7 +678,11 @@ fn check_item<'tcx>(
644678

645679
// And we access the Map here to get HirId from LocalDefId
646680
for id in local_def_ids {
647-
if of_trait {
681+
// for impl trait blocks, mark associate functions live if the trait is public
682+
if of_trait
683+
&& (!matches!(tcx.def_kind(id), DefKind::AssocFn)
684+
|| tcx.local_visibility(id) == Visibility::Public)
685+
{
648686
worklist.push((id, ComesFromAllowExpect::No));
649687
} else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) {
650688
worklist.push((id, comes_from_allow));
@@ -675,7 +713,7 @@ fn check_trait_item(
675713
use hir::TraitItemKind::{Const, Fn};
676714
if matches!(tcx.def_kind(id.owner_id), DefKind::AssocConst | DefKind::AssocFn) {
677715
let trait_item = tcx.hir().trait_item(id);
678-
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(_, hir::TraitFn::Provided(_)))
716+
if matches!(trait_item.kind, Const(_, Some(_)) | Fn(..))
679717
&& let Some(comes_from_allow) =
680718
has_allow_dead_code_or_lang_attr(tcx, trait_item.owner_id.def_id)
681719
{
@@ -944,7 +982,8 @@ impl<'tcx> DeadVisitor<'tcx> {
944982
| DefKind::TyAlias
945983
| DefKind::Enum
946984
| DefKind::Union
947-
| DefKind::ForeignTy => self.warn_dead_code(def_id, "used"),
985+
| DefKind::ForeignTy
986+
| DefKind::Trait => self.warn_dead_code(def_id, "used"),
948987
DefKind::Struct => self.warn_dead_code(def_id, "constructed"),
949988
DefKind::Variant | DefKind::Field => bug!("should be handled specially"),
950989
_ => {}
@@ -969,18 +1008,33 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9691008
let module_items = tcx.hir_module_items(module);
9701009

9711010
for item in module_items.items() {
972-
if let hir::ItemKind::Impl(impl_item) = tcx.hir().item(item).kind {
973-
let mut dead_items = Vec::new();
974-
for item in impl_item.items {
975-
let def_id = item.id.owner_id.def_id;
976-
if !visitor.is_live_code(def_id) {
977-
let name = tcx.item_name(def_id.to_def_id());
978-
let level = visitor.def_lint_level(def_id);
1011+
let def_kind = tcx.def_kind(item.owner_id);
9791012

980-
dead_items.push(DeadItem { def_id, name, level })
1013+
let mut dead_codes = Vec::new();
1014+
// if we have diagnosed the trait, do not diagnose unused methods
1015+
if matches!(def_kind, DefKind::Impl { .. })
1016+
|| (def_kind == DefKind::Trait && live_symbols.contains(&item.owner_id.def_id))
1017+
{
1018+
for &def_id in tcx.associated_item_def_ids(item.owner_id.def_id) {
1019+
// We have diagnosed unused methods in traits
1020+
if matches!(def_kind, DefKind::Impl { of_trait: true })
1021+
&& tcx.def_kind(def_id) == DefKind::AssocFn
1022+
|| def_kind == DefKind::Trait && tcx.def_kind(def_id) != DefKind::AssocFn
1023+
{
1024+
continue;
1025+
}
1026+
1027+
if let Some(local_def_id) = def_id.as_local()
1028+
&& !visitor.is_live_code(local_def_id)
1029+
{
1030+
let name = tcx.item_name(def_id);
1031+
let level = visitor.def_lint_level(local_def_id);
1032+
dead_codes.push(DeadItem { def_id: local_def_id, name, level });
9811033
}
9821034
}
983-
visitor.warn_multiple(item.owner_id.def_id, "used", dead_items, ReportOn::NamedField);
1035+
}
1036+
if !dead_codes.is_empty() {
1037+
visitor.warn_multiple(item.owner_id.def_id, "used", dead_codes, ReportOn::NamedField);
9841038
}
9851039

9861040
if !live_symbols.contains(&item.owner_id.def_id) {
@@ -993,7 +1047,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
9931047
continue;
9941048
}
9951049

996-
let def_kind = tcx.def_kind(item.owner_id);
9971050
if let DefKind::Struct | DefKind::Union | DefKind::Enum = def_kind {
9981051
let adt = tcx.adt_def(item.owner_id);
9991052
let mut dead_variants = Vec::new();
@@ -1040,8 +1093,6 @@ fn check_mod_deathness(tcx: TyCtxt<'_>, module: LocalModDefId) {
10401093
for foreign_item in module_items.foreign_items() {
10411094
visitor.check_definition(foreign_item.owner_id.def_id);
10421095
}
1043-
1044-
// We do not warn trait items.
10451096
}
10461097

10471098
pub(crate) fn provide(providers: &mut Providers) {

compiler/rustc_span/src/source_map/tests.rs

+2-47
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use super::*;
22

3+
use rustc_data_structures::sync::FreezeLock;
4+
35
fn init_source_map() -> SourceMap {
46
let sm = SourceMap::new(FilePathMapping::empty());
57
sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string());
@@ -263,53 +265,6 @@ fn t10() {
263265
);
264266
}
265267

266-
/// Returns the span corresponding to the `n`th occurrence of `substring` in `source_text`.
267-
trait SourceMapExtension {
268-
fn span_substr(
269-
&self,
270-
file: &Lrc<SourceFile>,
271-
source_text: &str,
272-
substring: &str,
273-
n: usize,
274-
) -> Span;
275-
}
276-
277-
impl SourceMapExtension for SourceMap {
278-
fn span_substr(
279-
&self,
280-
file: &Lrc<SourceFile>,
281-
source_text: &str,
282-
substring: &str,
283-
n: usize,
284-
) -> Span {
285-
eprintln!(
286-
"span_substr(file={:?}/{:?}, substring={:?}, n={})",
287-
file.name, file.start_pos, substring, n
288-
);
289-
let mut i = 0;
290-
let mut hi = 0;
291-
loop {
292-
let offset = source_text[hi..].find(substring).unwrap_or_else(|| {
293-
panic!(
294-
"source_text `{}` does not have {} occurrences of `{}`, only {}",
295-
source_text, n, substring, i
296-
);
297-
});
298-
let lo = hi + offset;
299-
hi = lo + substring.len();
300-
if i == n {
301-
let span = Span::with_root_ctxt(
302-
BytePos(lo as u32 + file.start_pos.0),
303-
BytePos(hi as u32 + file.start_pos.0),
304-
);
305-
assert_eq!(&self.span_to_snippet(span).unwrap()[..], substring);
306-
return span;
307-
}
308-
i += 1;
309-
}
310-
}
311-
}
312-
313268
// Takes a unix-style path and returns a platform specific path.
314269
fn path(p: &str) -> PathBuf {
315270
path_str(p).into()

library/core/tests/macros.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#[allow(dead_code)]
12
trait Trait {
23
fn blah(&self);
34
}

src/bootstrap/src/core/build_steps/setup.rs

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ static SETTINGS_HASHES: &[&str] = &[
3737
"3468fea433c25fff60be6b71e8a215a732a7b1268b6a83bf10d024344e140541",
3838
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
3939
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
40+
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
4041
];
4142
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");
4243

src/etc/rust_analyzer_settings.json

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"git.detectSubmodulesLimit": 20,
23
"rust-analyzer.check.invocationLocation": "root",
34
"rust-analyzer.check.invocationStrategy": "once",
45
"rust-analyzer.check.overrideCommand": [

src/librustdoc/passes/stripper.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,10 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
5656
| clean::TraitItem(..)
5757
| clean::FunctionItem(..)
5858
| clean::VariantItem(..)
59-
| clean::MethodItem(..)
6059
| clean::ForeignFunctionItem(..)
6160
| clean::ForeignStaticItem(..)
6261
| clean::ConstantItem(..)
6362
| clean::UnionItem(..)
64-
| clean::AssocConstItem(..)
65-
| clean::AssocTypeItem(..)
6663
| clean::TraitAliasItem(..)
6764
| clean::MacroItem(..)
6865
| clean::ForeignTypeItem => {
@@ -80,6 +77,16 @@ impl<'a, 'tcx> DocFolder for Stripper<'a, 'tcx> {
8077
}
8178
}
8279

80+
clean::MethodItem(..) | clean::AssocConstItem(..) | clean::AssocTypeItem(..) => {
81+
let item_id = i.item_id;
82+
if item_id.is_local()
83+
&& !self.effective_visibilities.is_reachable(self.tcx, item_id.expect_def_id())
84+
{
85+
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
86+
return None;
87+
}
88+
}
89+
8390
clean::StructFieldItem(..) => {
8491
if i.visibility(self.tcx) != Some(Visibility::Public) {
8592
return Some(strip_item(i));
@@ -192,16 +199,16 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
192199
&& imp.items.iter().all(|i| {
193200
let item_id = i.item_id;
194201
item_id.is_local()
195-
&& !is_item_reachable(
196-
self.tcx,
197-
self.is_json_output,
198-
&self.cache.effective_visibilities,
199-
item_id,
200-
)
202+
&& !self
203+
.cache
204+
.effective_visibilities
205+
.is_reachable(self.tcx, item_id.expect_def_id())
201206
})
202207
{
208+
debug!("ImplStripper: no public item; removing {imp:?}");
203209
return None;
204210
} else if imp.items.is_empty() && i.doc_value().is_empty() {
211+
debug!("ImplStripper: no item and no doc; removing {imp:?}");
205212
return None;
206213
}
207214
}
@@ -212,21 +219,21 @@ impl<'a> DocFolder for ImplStripper<'a, '_> {
212219
&& !imp.for_.is_assoc_ty()
213220
&& !self.should_keep_impl(&i, did)
214221
{
215-
debug!("ImplStripper: impl item for stripped type; removing");
222+
debug!("ImplStripper: impl item for stripped type; removing {imp:?}");
216223
return None;
217224
}
218225
if let Some(did) = imp.trait_.as_ref().map(|t| t.def_id())
219226
&& !self.should_keep_impl(&i, did)
220227
{
221-
debug!("ImplStripper: impl item for stripped trait; removing");
228+
debug!("ImplStripper: impl item for stripped trait; removing {imp:?}");
222229
return None;
223230
}
224231
if let Some(generics) = imp.trait_.as_ref().and_then(|t| t.generics()) {
225232
for typaram in generics {
226233
if let Some(did) = typaram.def_id(self.cache)
227234
&& !self.should_keep_impl(&i, did)
228235
{
229-
debug!("ImplStripper: stripped item in trait's generics; removing impl");
236+
debug!("ImplStripper: stripped item in trait's generics; removing {imp:?}");
230237
return None;
231238
}
232239
}

src/tools/clippy/clippy_lints/src/derive.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -451,12 +451,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
451451
&& let Some(def_id) = trait_ref.trait_def_id()
452452
&& cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
453453
&& let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
454-
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[])
454+
&& !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[])
455455
// If all of our fields implement `Eq`, we can implement `Eq` too
456456
&& adt
457457
.all_fields()
458458
.map(|f| f.ty(cx.tcx, args))
459-
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[]))
459+
.all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, None, &[]))
460460
{
461461
span_lint_and_sugg(
462462
cx,

src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>(
118118
.liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
119119
&& let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
120120
&& let param_env = cx.tcx.param_env(fn_id)
121-
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[])
121+
&& implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, Some(fn_id), &[])
122122
&& let Some(into_iter_ty) =
123123
make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty])
124124
&& let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)

0 commit comments

Comments
 (0)