Skip to content

Commit 91d7588

Browse files
authored
Merge branch 'master' into if_then_panic
2 parents 5f750a8 + cd3f3cf commit 91d7588

File tree

75 files changed

+1045
-349
lines changed

Some content is hidden

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

75 files changed

+1045
-349
lines changed

.github/ISSUE_TEMPLATE/blank_issue.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ about: Create a blank issue.
88
Additional labels can be added to this issue by including the following command
99
(without the space after the @ symbol):
1010
11-
`@rustbot label +<label>`
11+
@ rustbot label +<label>
1212
1313
Common labels for this issue type are:
1414
* C-an-interesting-project

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ LLVM version: 10.0
3636
Additional labels can be added to this issue by including the following command
3737
(without the space after the @ symbol):
3838
39-
`@rustbot label +<label>`
39+
@ rustbot label +<label>
4040
4141
Common labels for this issue type are:
4242
* `I-suggestion-causes-error`

.github/ISSUE_TEMPLATE/false_positive.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ LLVM version: 10.0
3737
Additional labels can be added to this issue by including the following command
3838
(without the space after the @ symbol):
3939
40-
`@rustbot label +<label>`
40+
@ rustbot label +<label>
4141
4242
Common labels for this issue type are:
4343
* I-suggestion-causes-error

CHANGELOG.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ Released 2020-11-19
10501050
[#5913](https://github.com/rust-lang/rust-clippy/pull/5913)
10511051
* Add example of false positive to [`ptr_arg`] docs.
10521052
[#5885](https://github.com/rust-lang/rust-clippy/pull/5885)
1053-
* [`box_vec`], [`vec_box`] and [`borrowed_box`]: add link to the documentation of `Box`
1053+
* [`box_vec`](https://rust-lang.github.io/rust-clippy/master/index.html#box_collection), [`vec_box`] and [`borrowed_box`]: add link to the documentation of `Box`
10541054
[#6023](https://github.com/rust-lang/rust-clippy/pull/6023)
10551055

10561056
## Rust 1.47
@@ -2570,7 +2570,7 @@ Released 2018-09-13
25702570
[`bool_comparison`]: https://rust-lang.github.io/rust-clippy/master/index.html#bool_comparison
25712571
[`borrow_interior_mutable_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const
25722572
[`borrowed_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#borrowed_box
2573-
[`box_vec`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_vec
2573+
[`box_collection`]: https://rust-lang.github.io/rust-clippy/master/index.html#box_collection
25742574
[`boxed_local`]: https://rust-lang.github.io/rust-clippy/master/index.html#boxed_local
25752575
[`branches_sharing_code`]: https://rust-lang.github.io/rust-clippy/master/index.html#branches_sharing_code
25762576
[`builtin_type_shadow`]: https://rust-lang.github.io/rust-clippy/master/index.html#builtin_type_shadow
@@ -2907,6 +2907,7 @@ Released 2018-09-13
29072907
[`reversed_empty_ranges`]: https://rust-lang.github.io/rust-clippy/master/index.html#reversed_empty_ranges
29082908
[`same_functions_in_if_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_functions_in_if_condition
29092909
[`same_item_push`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_item_push
2910+
[`same_name_method`]: https://rust-lang.github.io/rust-clippy/master/index.html#same_name_method
29102911
[`search_is_some`]: https://rust-lang.github.io/rust-clippy/master/index.html#search_is_some
29112912
[`self_assignment`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_assignment
29122913
[`self_named_constructors`]: https://rust-lang.github.io/rust-clippy/master/index.html#self_named_constructors

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ You can choose how much Clippy is supposed to ~~annoy~~ help you by changing the
1818
| `clippy::style` | code that should be written in a more idiomatic way | **warn** |
1919
| `clippy::complexity` | code that does something simple but in a complex way | **warn** |
2020
| `clippy::perf` | code that can be written to run faster | **warn** |
21-
| `clippy::pedantic` | lints which are rather strict or might have false positives | allow |
21+
| `clippy::pedantic` | lints which are rather strict or have occasional false positives | allow |
2222
| `clippy::nursery` | new lints that are still under development | allow |
2323
| `clippy::cargo` | lints for the cargo manifest | allow |
2424

clippy_lints/src/formatting.rs

Lines changed: 31 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -286,34 +286,39 @@ fn check_array(cx: &EarlyContext<'_>, expr: &Expr) {
286286
}
287287

288288
fn check_missing_else(cx: &EarlyContext<'_>, first: &Expr, second: &Expr) {
289-
if !differing_macro_contexts(first.span, second.span)
290-
&& !first.span.from_expansion()
291-
&& is_if(first)
292-
&& (is_block(second) || is_if(second))
293-
{
294-
// where the else would be
295-
let else_span = first.span.between(second.span);
289+
if_chain! {
290+
if !differing_macro_contexts(first.span, second.span);
291+
if !first.span.from_expansion();
292+
if let ExprKind::If(cond_expr, ..) = &first.kind;
293+
if is_block(second) || is_if(second);
296294

297-
if let Some(else_snippet) = snippet_opt(cx, else_span) {
298-
if !else_snippet.contains('\n') {
299-
let (looks_like, next_thing) = if is_if(second) {
300-
("an `else if`", "the second `if`")
301-
} else {
302-
("an `else {..}`", "the next block")
303-
};
295+
// Proc-macros can give weird spans. Make sure this is actually an `if`.
296+
if let Some(if_snip) = snippet_opt(cx, first.span.until(cond_expr.span));
297+
if if_snip.starts_with("if");
304298

305-
span_lint_and_note(
306-
cx,
307-
SUSPICIOUS_ELSE_FORMATTING,
308-
else_span,
309-
&format!("this looks like {} but the `else` is missing", looks_like),
310-
None,
311-
&format!(
312-
"to remove this lint, add the missing `else` or add a new line before {}",
313-
next_thing,
314-
),
315-
);
316-
}
299+
// If there is a line break between the two expressions, don't lint.
300+
// If there is a non-whitespace character, this span came from a proc-macro.
301+
let else_span = first.span.between(second.span);
302+
if let Some(else_snippet) = snippet_opt(cx, else_span);
303+
if !else_snippet.chars().any(|c| c == '\n' || !c.is_whitespace());
304+
then {
305+
let (looks_like, next_thing) = if is_if(second) {
306+
("an `else if`", "the second `if`")
307+
} else {
308+
("an `else {..}`", "the next block")
309+
};
310+
311+
span_lint_and_note(
312+
cx,
313+
SUSPICIOUS_ELSE_FORMATTING,
314+
else_span,
315+
&format!("this looks like {} but the `else` is missing", looks_like),
316+
None,
317+
&format!(
318+
"to remove this lint, add the missing `else` or add a new line before {}",
319+
next_thing,
320+
),
321+
);
317322
}
318323
}
319324
}

clippy_lints/src/lib.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,7 @@ mod reference;
332332
mod regex;
333333
mod repeat_once;
334334
mod returns;
335+
mod same_name_method;
335336
mod self_assignment;
336337
mod self_named_constructors;
337338
mod semicolon_if_nothing_returned;
@@ -912,6 +913,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
912913
repeat_once::REPEAT_ONCE,
913914
returns::LET_AND_RETURN,
914915
returns::NEEDLESS_RETURN,
916+
same_name_method::SAME_NAME_METHOD,
915917
self_assignment::SELF_ASSIGNMENT,
916918
self_named_constructors::SELF_NAMED_CONSTRUCTORS,
917919
semicolon_if_nothing_returned::SEMICOLON_IF_NOTHING_RETURNED,
@@ -956,7 +958,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
956958
transmuting_null::TRANSMUTING_NULL,
957959
try_err::TRY_ERR,
958960
types::BORROWED_BOX,
959-
types::BOX_VEC,
961+
types::BOX_COLLECTION,
960962
types::LINKEDLIST,
961963
types::OPTION_OPTION,
962964
types::RC_BUFFER,
@@ -1055,6 +1057,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
10551057
LintId::of(panic_unimplemented::UNIMPLEMENTED),
10561058
LintId::of(panic_unimplemented::UNREACHABLE),
10571059
LintId::of(pattern_type_mismatch::PATTERN_TYPE_MISMATCH),
1060+
LintId::of(same_name_method::SAME_NAME_METHOD),
10581061
LintId::of(shadow::SHADOW_REUSE),
10591062
LintId::of(shadow::SHADOW_SAME),
10601063
LintId::of(strings::STRING_ADD),
@@ -1139,6 +1142,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
11391142
LintId::of(needless_continue::NEEDLESS_CONTINUE),
11401143
LintId::of(needless_for_each::NEEDLESS_FOR_EACH),
11411144
LintId::of(needless_pass_by_value::NEEDLESS_PASS_BY_VALUE),
1145+
LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
11421146
LintId::of(non_expressive_names::SIMILAR_NAMES),
11431147
LintId::of(pass_by_ref_or_value::LARGE_TYPES_PASSED_BY_VALUE),
11441148
LintId::of(pass_by_ref_or_value::TRIVIALLY_COPY_PASS_BY_REF),
@@ -1396,7 +1400,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
13961400
LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
13971401
LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
13981402
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
1399-
LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
14001403
LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
14011404
LintId::of(open_options::NONSENSICAL_OPEN_OPTIONS),
14021405
LintId::of(option_env_unwrap::OPTION_ENV_UNWRAP),
@@ -1454,7 +1457,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
14541457
LintId::of(transmuting_null::TRANSMUTING_NULL),
14551458
LintId::of(try_err::TRY_ERR),
14561459
LintId::of(types::BORROWED_BOX),
1457-
LintId::of(types::BOX_VEC),
1460+
LintId::of(types::BOX_COLLECTION),
14581461
LintId::of(types::REDUNDANT_ALLOCATION),
14591462
LintId::of(types::TYPE_COMPLEXITY),
14601463
LintId::of(types::VEC_BOX),
@@ -1571,7 +1574,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15711574
LintId::of(non_copy_const::BORROW_INTERIOR_MUTABLE_CONST),
15721575
LintId::of(non_copy_const::DECLARE_INTERIOR_MUTABLE_CONST),
15731576
LintId::of(non_expressive_names::JUST_UNDERSCORES_AND_DIGITS),
1574-
LintId::of(non_expressive_names::MANY_SINGLE_CHAR_NAMES),
15751577
LintId::of(ptr::CMP_NULL),
15761578
LintId::of(ptr::PTR_ARG),
15771579
LintId::of(ptr_eq::PTR_EQ),
@@ -1794,7 +1796,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
17941796
LintId::of(redundant_clone::REDUNDANT_CLONE),
17951797
LintId::of(slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
17961798
LintId::of(stable_sort_primitive::STABLE_SORT_PRIMITIVE),
1797-
LintId::of(types::BOX_VEC),
1799+
LintId::of(types::BOX_COLLECTION),
17981800
LintId::of(types::REDUNDANT_ALLOCATION),
17991801
LintId::of(vec::USELESS_VEC),
18001802
LintId::of(vec_init_then_push::VEC_INIT_THEN_PUSH),
@@ -1927,6 +1929,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
19271929
store.register_early_pass(move || Box::new(unnested_or_patterns::UnnestedOrPatterns::new(msrv)));
19281930

19291931
store.register_late_pass(|| Box::new(size_of_in_element_count::SizeOfInElementCount));
1932+
store.register_late_pass(|| Box::new(same_name_method::SameNameMethod));
19301933
store.register_late_pass(|| Box::new(map_clone::MapClone));
19311934
store.register_late_pass(|| Box::new(map_err_ignore::MapErrIgnore));
19321935
store.register_late_pass(|| Box::new(shadow::Shadow));
@@ -2195,6 +2198,7 @@ pub fn register_renamed(ls: &mut rustc_lint::LintStore) {
21952198
ls.register_renamed("clippy::cyclomatic_complexity", "clippy::cognitive_complexity");
21962199
ls.register_renamed("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes");
21972200
ls.register_renamed("clippy::option_and_then_some", "clippy::bind_instead_of_map");
2201+
ls.register_renamed("clippy::box_vec", "clippy::box_collection");
21982202
ls.register_renamed("clippy::block_in_if_condition_expr", "clippy::blocks_in_if_conditions");
21992203
ls.register_renamed("clippy::block_in_if_condition_stmt", "clippy::blocks_in_if_conditions");
22002204
ls.register_renamed("clippy::option_map_unwrap_or", "clippy::map_unwrap_or");

clippy_lints/src/loops/while_let_on_iterator.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use clippy_utils::{
88
use if_chain::if_chain;
99
use rustc_errors::Applicability;
1010
use rustc_hir::intravisit::{walk_expr, ErasedMap, NestedVisitorMap, Visitor};
11-
use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
11+
use rustc_hir::{def::Res, Expr, ExprKind, HirId, Local, PatKind, QPath, UnOp};
1212
use rustc_lint::LateContext;
1313
use rustc_span::{symbol::sym, Span, Symbol};
1414

@@ -47,13 +47,8 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
4747
// If the iterator is a field or the iterator is accessed after the loop is complete it needs to be
4848
// borrowed mutably. TODO: If the struct can be partially moved from and the struct isn't used
4949
// afterwards a mutable borrow of a field isn't necessary.
50-
let ref_mut = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) {
51-
if cx.typeck_results().node_type(iter_expr.hir_id).ref_mutability() == Some(Mutability::Mut) {
52-
// Reborrow for mutable references. It may not be possible to get a mutable reference here.
53-
"&mut *"
54-
} else {
55-
"&mut "
56-
}
50+
let by_ref = if !iter_expr.fields.is_empty() || needs_mutable_borrow(cx, &iter_expr, loop_expr) {
51+
".by_ref()"
5752
} else {
5853
""
5954
};
@@ -65,7 +60,7 @@ pub(super) fn check(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
6560
expr.span.with_hi(scrutinee_expr.span.hi()),
6661
"this loop could be written as a `for` loop",
6762
"try",
68-
format!("for {} in {}{}", loop_var, ref_mut, iterator),
63+
format!("for {} in {}{}", loop_var, iterator, by_ref),
6964
applicability,
7065
);
7166
}

clippy_lints/src/methods/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ declare_clippy_lint! {
264264
/// The method signature is controlled by the trait and often `&self` is required for all types that implement the trait
265265
/// (see e.g. the `std::string::ToString` trait).
266266
///
267+
/// Clippy allows `Pin<&Self>` and `Pin<&mut Self>` if `&self` and `&mut self` is required.
268+
///
267269
/// Please find more info here:
268270
/// https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv
269271
///

clippy_lints/src/mut_key.rs

Lines changed: 61 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use clippy_utils::trait_ref_of_method;
33
use rustc_hir as hir;
44
use rustc_lint::{LateContext, LateLintPass};
55
use rustc_middle::ty::TypeFoldable;
6-
use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut};
6+
use rustc_middle::ty::{Adt, Array, Ref, Slice, Tuple, Ty};
77
use rustc_session::{declare_lint_pass, declare_tool_lint};
88
use rustc_span::source_map::Span;
99
use rustc_span::symbol::sym;
@@ -19,10 +19,29 @@ declare_clippy_lint! {
1919
/// so having types with interior mutability is a bad idea.
2020
///
2121
/// ### Known problems
22-
/// It's correct to use a struct, that contains interior mutability
23-
/// as a key, when its `Hash` implementation doesn't access any of the interior mutable types.
24-
/// However, this lint is unable to recognize this, so it causes a false positive in theses cases.
25-
/// The `bytes` crate is a great example of this.
22+
///
23+
/// #### False Positives
24+
/// It's correct to use a struct that contains interior mutability as a key, when its
25+
/// implementation of `Hash` or `Ord` doesn't access any of the interior mutable types.
26+
/// However, this lint is unable to recognize this, so it will often cause false positives in
27+
/// theses cases. The `bytes` crate is a great example of this.
28+
///
29+
/// #### False Negatives
30+
/// For custom `struct`s/`enum`s, this lint is unable to check for interior mutability behind
31+
/// indirection. For example, `struct BadKey<'a>(&'a Cell<usize>)` will be seen as immutable
32+
/// and cause a false negative if its implementation of `Hash`/`Ord` accesses the `Cell`.
33+
///
34+
/// This lint does check a few cases for indirection. Firstly, using some standard library
35+
/// types (`Option`, `Result`, `Box`, `Rc`, `Arc`, `Vec`, `VecDeque`, `BTreeMap` and
36+
/// `BTreeSet`) directly as keys (e.g. in `HashMap<Box<Cell<usize>>, ()>`) **will** trigger the
37+
/// lint, because the impls of `Hash`/`Ord` for these types directly call `Hash`/`Ord` on their
38+
/// contained type.
39+
///
40+
/// Secondly, the implementations of `Hash` and `Ord` for raw pointers (`*const T` or `*mut T`)
41+
/// apply only to the **address** of the contained value. Therefore, interior mutability
42+
/// behind raw pointers (e.g. in `HashSet<*mut Cell<usize>>`) can't impact the value of `Hash`
43+
/// or `Ord`, and therefore will not trigger this link. For more info, see issue
44+
/// [#6745](https://github.com/rust-lang/rust-clippy/issues/6745).
2645
///
2746
/// ### Example
2847
/// ```rust
@@ -103,30 +122,52 @@ fn check_sig<'tcx>(cx: &LateContext<'tcx>, item_hir_id: hir::HirId, decl: &hir::
103122
fn check_ty<'tcx>(cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
104123
let ty = ty.peel_refs();
105124
if let Adt(def, substs) = ty.kind() {
106-
if [sym::hashmap_type, sym::BTreeMap, sym::hashset_type, sym::BTreeMap]
125+
let is_keyed_type = [sym::hashmap_type, sym::BTreeMap, sym::hashset_type, sym::BTreeSet]
107126
.iter()
108-
.any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did))
109-
&& is_mutable_type(cx, substs.type_at(0), span)
110-
{
127+
.any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did));
128+
if is_keyed_type && is_interior_mutable_type(cx, substs.type_at(0), span) {
111129
span_lint(cx, MUTABLE_KEY_TYPE, span, "mutable key type");
112130
}
113131
}
114132
}
115133

116-
fn is_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
134+
/// Determines if a type contains interior mutability which would affect its implementation of
135+
/// [`Hash`] or [`Ord`].
136+
fn is_interior_mutable_type<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, span: Span) -> bool {
117137
match *ty.kind() {
118-
RawPtr(TypeAndMut { ty: inner_ty, mutbl }) | Ref(_, inner_ty, mutbl) => {
119-
mutbl == hir::Mutability::Mut || is_mutable_type(cx, inner_ty, span)
120-
},
121-
Slice(inner_ty) => is_mutable_type(cx, inner_ty, span),
138+
Ref(_, inner_ty, mutbl) => mutbl == hir::Mutability::Mut || is_interior_mutable_type(cx, inner_ty, span),
139+
Slice(inner_ty) => is_interior_mutable_type(cx, inner_ty, span),
122140
Array(inner_ty, size) => {
123-
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0) && is_mutable_type(cx, inner_ty, span)
141+
size.try_eval_usize(cx.tcx, cx.param_env).map_or(true, |u| u != 0)
142+
&& is_interior_mutable_type(cx, inner_ty, span)
124143
},
125-
Tuple(..) => ty.tuple_fields().any(|ty| is_mutable_type(cx, ty, span)),
126-
Adt(..) => {
127-
!ty.has_escaping_bound_vars()
128-
&& cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
129-
&& !ty.is_freeze(cx.tcx.at(span), cx.param_env)
144+
Tuple(..) => ty.tuple_fields().any(|ty| is_interior_mutable_type(cx, ty, span)),
145+
Adt(def, substs) => {
146+
// Special case for collections in `std` who's impl of `Hash` or `Ord` delegates to
147+
// that of their type parameters. Note: we don't include `HashSet` and `HashMap`
148+
// because they have no impl for `Hash` or `Ord`.
149+
let is_std_collection = [
150+
sym::option_type,
151+
sym::result_type,
152+
sym::LinkedList,
153+
sym::vec_type,
154+
sym::vecdeque_type,
155+
sym::BTreeMap,
156+
sym::BTreeSet,
157+
sym::Rc,
158+
sym::Arc,
159+
]
160+
.iter()
161+
.any(|diag_item| cx.tcx.is_diagnostic_item(*diag_item, def.did));
162+
let is_box = Some(def.did) == cx.tcx.lang_items().owned_box();
163+
if is_std_collection || is_box {
164+
// The type is mutable if any of its type parameters are
165+
substs.types().any(|ty| is_interior_mutable_type(cx, ty, span))
166+
} else {
167+
!ty.has_escaping_bound_vars()
168+
&& cx.tcx.layout_of(cx.param_env.and(ty)).is_ok()
169+
&& !ty.is_freeze(cx.tcx.at(span), cx.param_env)
170+
}
130171
},
131172
_ => false,
132173
}

0 commit comments

Comments
 (0)