Skip to content

Commit 8fd946c

Browse files
committed
Auto merge of #82795 - m-ou-se:rollup-uzx0b92, r=m-ou-se
Rollup of 10 pull requests Successful merges: - #80723 (Implement NOOP_METHOD_CALL lint) - #80763 (resolve: Reduce scope of `pub_use_of_private_extern_crate` deprecation lint) - #81136 (Improved IO Bytes Size Hint) - #81939 (Add suggestion `.collect()` for iterators in iterators) - #82289 (Fix underflow in specialized ZipImpl::size_hint) - #82728 (Avoid unnecessary Vec construction in BufReader) - #82764 (Add {BTreeMap,HashMap}::try_insert) - #82770 (Add assert_matches macro.) - #82773 (Add diagnostic item to `Default` trait) - #82787 (Remove unused code from main.js) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents 8ccc89b + 16518e7 commit 8fd946c

File tree

46 files changed

+776
-117
lines changed

Some content is hidden

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

46 files changed

+776
-117
lines changed

compiler/rustc_codegen_ssa/src/back/rpath.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub fn get_rpath_flags(config: &mut RPathConfig<'_>) -> Vec<String> {
2424

2525
debug!("preparing the RPATH!");
2626

27-
let libs = config.used_crates.clone();
27+
let libs = config.used_crates;
2828
let libs = libs.iter().filter_map(|&(_, ref l)| l.option()).collect::<Vec<_>>();
2929
let rpaths = get_rpaths(config, &libs);
3030
let mut flags = rpaths_to_flags(&rpaths);

compiler/rustc_lint/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ mod methods;
5757
mod non_ascii_idents;
5858
mod non_fmt_panic;
5959
mod nonstandard_style;
60+
mod noop_method_call;
6061
mod passes;
6162
mod redundant_semicolon;
6263
mod traits;
@@ -81,6 +82,7 @@ use methods::*;
8182
use non_ascii_idents::*;
8283
use non_fmt_panic::NonPanicFmt;
8384
use nonstandard_style::*;
85+
use noop_method_call::*;
8486
use redundant_semicolon::*;
8587
use traits::*;
8688
use types::*;
@@ -168,6 +170,7 @@ macro_rules! late_lint_passes {
168170
DropTraitConstraints: DropTraitConstraints,
169171
TemporaryCStringAsPtr: TemporaryCStringAsPtr,
170172
NonPanicFmt: NonPanicFmt,
173+
NoopMethodCall: NoopMethodCall,
171174
]
172175
);
173176
};
+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use crate::context::LintContext;
2+
use crate::rustc_middle::ty::TypeFoldable;
3+
use crate::LateContext;
4+
use crate::LateLintPass;
5+
use rustc_hir::def::DefKind;
6+
use rustc_hir::{Expr, ExprKind};
7+
use rustc_middle::ty;
8+
use rustc_span::symbol::sym;
9+
10+
declare_lint! {
11+
/// The `noop_method_call` lint detects specific calls to noop methods
12+
/// such as a calling `<&T as Clone>::clone` where `T: !Clone`.
13+
///
14+
/// ### Example
15+
///
16+
/// ```rust
17+
/// # #![allow(unused)]
18+
/// #![warn(noop_method_call)]
19+
/// struct Foo;
20+
/// let foo = &Foo;
21+
/// let clone: &Foo = foo.clone();
22+
/// ```
23+
///
24+
/// {{produces}}
25+
///
26+
/// ### Explanation
27+
///
28+
/// Some method calls are noops meaning that they do nothing. Usually such methods
29+
/// are the result of blanket implementations that happen to create some method invocations
30+
/// that end up not doing anything. For instance, `Clone` is implemented on all `&T`, but
31+
/// calling `clone` on a `&T` where `T` does not implement clone, actually doesn't do anything
32+
/// as references are copy. This lint detects these calls and warns the user about them.
33+
pub NOOP_METHOD_CALL,
34+
Allow,
35+
"detects the use of well-known noop methods"
36+
}
37+
38+
declare_lint_pass!(NoopMethodCall => [NOOP_METHOD_CALL]);
39+
40+
impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
41+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
42+
// We only care about method calls.
43+
let (call, elements) = match expr.kind {
44+
ExprKind::MethodCall(call, _, elements, _) => (call, elements),
45+
_ => return,
46+
};
47+
// We only care about method calls corresponding to the `Clone`, `Deref` and `Borrow`
48+
// traits and ignore any other method call.
49+
let (trait_id, did) = match cx.typeck_results().type_dependent_def(expr.hir_id) {
50+
// Verify we are dealing with a method/associated function.
51+
Some((DefKind::AssocFn, did)) => match cx.tcx.trait_of_item(did) {
52+
// Check that we're dealing with a trait method for one of the traits we care about.
53+
Some(trait_id)
54+
if [sym::Clone, sym::Deref, sym::Borrow]
55+
.iter()
56+
.any(|s| cx.tcx.is_diagnostic_item(*s, trait_id)) =>
57+
{
58+
(trait_id, did)
59+
}
60+
_ => return,
61+
},
62+
_ => return,
63+
};
64+
let substs = cx.typeck_results().node_substs(expr.hir_id);
65+
if substs.needs_subst() {
66+
// We can't resolve on types that require monomorphization, so we don't handle them if
67+
// we need to perfom substitution.
68+
return;
69+
}
70+
let param_env = cx.tcx.param_env(trait_id);
71+
// Resolve the trait method instance.
72+
let i = match ty::Instance::resolve(cx.tcx, param_env, did, substs) {
73+
Ok(Some(i)) => i,
74+
_ => return,
75+
};
76+
// (Re)check that it implements the noop diagnostic.
77+
for s in [sym::noop_method_clone, sym::noop_method_deref, sym::noop_method_borrow].iter() {
78+
if cx.tcx.is_diagnostic_item(*s, i.def_id()) {
79+
let method = &call.ident.name;
80+
let receiver = &elements[0];
81+
let receiver_ty = cx.typeck_results().expr_ty(receiver);
82+
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
83+
if receiver_ty != expr_ty {
84+
// This lint will only trigger if the receiver type and resulting expression \
85+
// type are the same, implying that the method call is unnecessary.
86+
return;
87+
}
88+
let expr_span = expr.span;
89+
let note = format!(
90+
"the type `{:?}` which `{}` is being called on is the same as \
91+
the type returned from `{}`, so the method call does not do \
92+
anything and can be removed",
93+
receiver_ty, method, method,
94+
);
95+
96+
let span = expr_span.with_lo(receiver.span.hi());
97+
cx.struct_span_lint(NOOP_METHOD_CALL, span, |lint| {
98+
let method = &call.ident.name;
99+
let message = format!(
100+
"call to `.{}()` on a reference in this situation does nothing",
101+
&method,
102+
);
103+
lint.build(&message)
104+
.span_label(span, "unnecessary method call")
105+
.note(&note)
106+
.emit()
107+
});
108+
}
109+
}
110+
}
111+
}

compiler/rustc_middle/src/ty/error.rs

-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_target::spec::abi;
1212

1313
use std::borrow::Cow;
1414
use std::fmt;
15-
use std::ops::Deref;
1615

1716
#[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable)]
1817
pub struct ExpectedFound<T> {
@@ -548,7 +547,6 @@ impl<T> Trait<T> for X {
548547
TargetFeatureCast(def_id) => {
549548
let attrs = self.get_attrs(*def_id);
550549
let target_spans = attrs
551-
.deref()
552550
.iter()
553551
.filter(|attr| attr.has_name(sym::target_feature))
554552
.map(|attr| attr.span);

compiler/rustc_mir/src/borrow_check/diagnostics/conflict_errors.rs

+29-4
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ use rustc_middle::mir::{
1010
FakeReadCause, Local, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
1111
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
1212
};
13-
use rustc_middle::ty::{self, suggest_constraining_type_param, Instance, Ty};
14-
use rustc_span::{source_map::DesugaringKind, symbol::sym, Span};
13+
use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TypeFoldable};
14+
use rustc_span::source_map::DesugaringKind;
15+
use rustc_span::symbol::sym;
16+
use rustc_span::Span;
1517

1618
use crate::dataflow::drop_flag_effects;
1719
use crate::dataflow::indexes::{MoveOutIndex, MovePathIndex};
1820
use crate::util::borrowck_errors;
1921

2022
use crate::borrow_check::{
21-
borrow_set::BorrowData, prefixes::IsPrefixOf, InitializationRequiringAction, MirBorrowckCtxt,
22-
PrefixSet, WriteKind,
23+
borrow_set::BorrowData, diagnostics::Instance, prefixes::IsPrefixOf,
24+
InitializationRequiringAction, MirBorrowckCtxt, PrefixSet, WriteKind,
2325
};
2426

2527
use super::{
@@ -1267,6 +1269,29 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12671269

12681270
if return_span != borrow_span {
12691271
err.span_label(borrow_span, note);
1272+
1273+
let tcx = self.infcx.tcx;
1274+
let ty_params = ty::List::empty();
1275+
1276+
let return_ty = self.regioncx.universal_regions().unnormalized_output_ty;
1277+
let return_ty = tcx.erase_regions(return_ty);
1278+
1279+
// to avoid panics
1280+
if !return_ty.has_infer_types() {
1281+
if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) {
1282+
if tcx.type_implements_trait((iter_trait, return_ty, ty_params, self.param_env))
1283+
{
1284+
if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(return_span) {
1285+
err.span_suggestion_hidden(
1286+
return_span,
1287+
"use `.collect()` to allocate the iterator",
1288+
format!("{}{}", snippet, ".collect::<Vec<_>>()"),
1289+
Applicability::MaybeIncorrect,
1290+
);
1291+
}
1292+
}
1293+
}
1294+
}
12701295
}
12711296

12721297
Some(err)

compiler/rustc_mir/src/borrow_check/invalidation.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
165165
self.consume_operand(location, value);
166166

167167
// Invalidate all borrows of local places
168-
let borrow_set = self.borrow_set.clone();
168+
let borrow_set = self.borrow_set;
169169
let resume = self.location_table.start_index(resume.start_location());
170170
for (i, data) in borrow_set.iter_enumerated() {
171171
if borrow_of_local_data(data.borrowed_place) {
@@ -177,7 +177,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
177177
}
178178
TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
179179
// Invalidate all borrows of local places
180-
let borrow_set = self.borrow_set.clone();
180+
let borrow_set = self.borrow_set;
181181
let start = self.location_table.start_index(location);
182182
for (i, data) in borrow_set.iter_enumerated() {
183183
if borrow_of_local_data(data.borrowed_place) {
@@ -369,15 +369,15 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> {
369369
);
370370
let tcx = self.tcx;
371371
let body = self.body;
372-
let borrow_set = self.borrow_set.clone();
372+
let borrow_set = self.borrow_set;
373373
let indices = self.borrow_set.indices();
374374
each_borrow_involving_path(
375375
self,
376376
tcx,
377377
body,
378378
location,
379379
(sd, place),
380-
&borrow_set.clone(),
380+
borrow_set,
381381
indices,
382382
|this, borrow_index, borrow| {
383383
match (rw, borrow.kind) {

compiler/rustc_mir_build/src/build/matches/test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5151

5252
PatKind::Constant { value } => Test {
5353
span: match_pair.pattern.span,
54-
kind: TestKind::Eq { value, ty: match_pair.pattern.ty.clone() },
54+
kind: TestKind::Eq { value, ty: match_pair.pattern.ty },
5555
},
5656

5757
PatKind::Range(range) => {

compiler/rustc_resolve/src/imports.rs

+20-12
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,21 @@ impl<'a> NameResolution<'a> {
156156
}
157157
}
158158

159+
// Reexports of the form `pub use foo as bar;` where `foo` is `extern crate foo;`
160+
// are permitted for backward-compatibility under a deprecation lint.
161+
fn pub_use_of_private_extern_crate_hack(import: &Import<'_>, binding: &NameBinding<'_>) -> bool {
162+
match (&import.kind, &binding.kind) {
163+
(
164+
ImportKind::Single { .. },
165+
NameBindingKind::Import {
166+
import: Import { kind: ImportKind::ExternCrate { .. }, .. },
167+
..
168+
},
169+
) => import.vis.get() == ty::Visibility::Public,
170+
_ => false,
171+
}
172+
}
173+
159174
impl<'a> Resolver<'a> {
160175
crate fn resolve_ident_in_module_unadjusted(
161176
&mut self,
@@ -263,10 +278,7 @@ impl<'a> Resolver<'a> {
263278
return Err((Determined, Weak::No));
264279
}
265280
}
266-
// `extern crate` are always usable for backwards compatibility, see issue #37020,
267-
// remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`.
268-
let usable = this.is_accessible_from(binding.vis, parent_scope.module)
269-
|| binding.is_extern_crate();
281+
let usable = this.is_accessible_from(binding.vis, parent_scope.module);
270282
if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
271283
};
272284

@@ -309,10 +321,7 @@ impl<'a> Resolver<'a> {
309321
}
310322
}
311323

312-
if !(self.is_accessible_from(binding.vis, parent_scope.module) ||
313-
// Remove this together with `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
314-
(self.last_import_segment && binding.is_extern_crate()))
315-
{
324+
if !self.is_accessible_from(binding.vis, parent_scope.module) {
316325
self.privacy_errors.push(PrivacyError {
317326
ident,
318327
binding,
@@ -455,9 +464,8 @@ impl<'a> Resolver<'a> {
455464
binding: &'a NameBinding<'a>,
456465
import: &'a Import<'a>,
457466
) -> &'a NameBinding<'a> {
458-
let vis = if binding.vis.is_at_least(import.vis.get(), self) ||
459-
// cf. `PUB_USE_OF_PRIVATE_EXTERN_CRATE`
460-
!import.is_glob() && binding.is_extern_crate()
467+
let vis = if binding.vis.is_at_least(import.vis.get(), self)
468+
|| pub_use_of_private_extern_crate_hack(import, binding)
461469
{
462470
import.vis.get()
463471
} else {
@@ -1188,7 +1196,7 @@ impl<'a, 'b> ImportResolver<'a, 'b> {
11881196
// All namespaces must be re-exported with extra visibility for an error to occur.
11891197
if !any_successful_reexport {
11901198
let (ns, binding) = reexport_error.unwrap();
1191-
if ns == TypeNS && binding.is_extern_crate() {
1199+
if pub_use_of_private_extern_crate_hack(import, binding) {
11921200
let msg = format!(
11931201
"extern crate `{}` is private, and cannot be \
11941202
re-exported (error E0365), consider declaring with \

compiler/rustc_span/src/symbol.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use crate::{Edition, Span, DUMMY_SP, SESSION_GLOBALS};
1818
#[cfg(test)]
1919
mod tests;
2020

21-
// The proc macro code for this is in `src/librustc_macros/src/symbols.rs`.
21+
// The proc macro code for this is in `compiler/rustc_macros/src/symbols.rs`.
2222
symbols! {
2323
// After modifying this list adjust `is_special`, `is_used_keyword`/`is_unused_keyword`,
2424
// this should be rarely necessary though if the keywords are kept in alphabetic order.
@@ -129,6 +129,7 @@ symbols! {
129129
BTreeMap,
130130
BTreeSet,
131131
BinaryHeap,
132+
Borrow,
132133
C,
133134
CString,
134135
Center,
@@ -141,6 +142,7 @@ symbols! {
141142
Decodable,
142143
Decoder,
143144
Default,
145+
Deref,
144146
Encodable,
145147
Encoder,
146148
Eq,
@@ -789,6 +791,9 @@ symbols! {
789791
none_error,
790792
nontemporal_store,
791793
nontrapping_dash_fptoint: "nontrapping-fptoint",
794+
noop_method_borrow,
795+
noop_method_clone,
796+
noop_method_deref,
792797
noreturn,
793798
nostack,
794799
not,

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
819819
sig.decl
820820
.inputs
821821
.iter()
822-
.map(|arg| match arg.clone().kind {
822+
.map(|arg| match arg.kind {
823823
hir::TyKind::Tup(ref tys) => ArgKind::Tuple(
824824
Some(arg.span),
825825
vec![("_".to_owned(), "_".to_owned()); tys.len()],

compiler/rustc_traits/src/chalk/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ crate fn evaluate_goal<'tcx>(
165165
// let's just ignore that
166166
let sol = Canonical {
167167
max_universe: ty::UniverseIndex::from_usize(0),
168-
variables: obligation.variables.clone(),
168+
variables: obligation.variables,
169169
value: QueryResponse {
170170
var_values: CanonicalVarValues { var_values: IndexVec::new() }
171171
.make_identity(tcx),

compiler/rustc_typeck/src/check/callee.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
465465
let expected_arg_tys = self.expected_inputs_for_expected_output(
466466
call_expr.span,
467467
expected,
468-
fn_sig.output().clone(),
468+
fn_sig.output(),
469469
fn_sig.inputs(),
470470
);
471471

compiler/rustc_typeck/src/check/expr.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
711711
});
712712

713713
let ret_ty = ret_coercion.borrow().expected_ty();
714-
let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty.clone());
714+
let return_expr_ty = self.check_expr_with_hint(return_expr, ret_ty);
715715
ret_coercion.borrow_mut().coerce(
716716
self,
717717
&self.cause(return_expr.span, ObligationCauseCode::ReturnValue(return_expr.hir_id)),

0 commit comments

Comments
 (0)