Skip to content

Commit 17067e9

Browse files
committed
Auto merge of #140859 - pietroalbini:pa-stable, r=pietroalbini
[stable] Prepare the 1.87.0 release Preparing the stable artifacts as described in the release process. This PR also includes the following last minute backports: * #140810 * #140601 * #140684 r? `@ghost`
2 parents af91af4 + 908c30b commit 17067e9

File tree

24 files changed

+551
-139
lines changed

24 files changed

+551
-139
lines changed

RELEASES.md

Lines changed: 289 additions & 0 deletions
Large diffs are not rendered by default.

compiler/rustc_attr_parsing/src/parser.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust;
1313
use rustc_errors::DiagCtxtHandle;
1414
use rustc_hir::{self as hir, AttrPath};
1515
use rustc_span::symbol::{Ident, kw, sym};
16-
use rustc_span::{ErrorGuaranteed, Span, Symbol};
16+
use rustc_span::{Span, Symbol};
1717

1818
pub struct SegmentIterator<'a> {
1919
offset: usize,
@@ -176,7 +176,7 @@ impl<'a> ArgParser<'a> {
176176
pub enum MetaItemOrLitParser<'a> {
177177
MetaItemParser(MetaItemParser<'a>),
178178
Lit(MetaItemLit),
179-
Err(Span, ErrorGuaranteed),
179+
Err(Span),
180180
}
181181

182182
impl<'a> MetaItemOrLitParser<'a> {
@@ -186,7 +186,7 @@ impl<'a> MetaItemOrLitParser<'a> {
186186
generic_meta_item_parser.span()
187187
}
188188
MetaItemOrLitParser::Lit(meta_item_lit) => meta_item_lit.span,
189-
MetaItemOrLitParser::Err(span, _) => *span,
189+
MetaItemOrLitParser::Err(span) => *span,
190190
}
191191
}
192192

@@ -495,12 +495,9 @@ impl<'a> MetaItemListParserContext<'a> {
495495
// where the macro didn't expand to a literal. An error is already given
496496
// for this at this point, and then we do continue. This makes this path
497497
// reachable...
498-
let e = self.dcx.span_delayed_bug(
499-
*span,
500-
"expr in place where literal is expected (builtin attr parsing)",
501-
);
502-
503-
return Some(MetaItemOrLitParser::Err(*span, e));
498+
// NOTE: For backward compatibility we can't emit any error / delayed bug here (yet).
499+
// See <https://github.com/rust-lang/rust/issues/140612>
500+
return Some(MetaItemOrLitParser::Err(*span));
504501
} else {
505502
self.next_path()?
506503
};

compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
146146

147147
let principal_trait = regular_traits.into_iter().next();
148148

149-
let mut needed_associated_types = vec![];
149+
// A stable ordering of associated types from the principal trait and all its
150+
// supertraits. We use this to ensure that different substitutions of a trait
151+
// don't result in `dyn Trait` types with different projections lists, which
152+
// can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
153+
// We achieve a stable ordering by walking over the unsubstituted principal
154+
// trait ref.
155+
let mut ordered_associated_types = vec![];
156+
150157
if let Some((principal_trait, ref spans)) = principal_trait {
151158
let principal_trait = principal_trait.map_bound(|trait_pred| {
152159
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
@@ -171,16 +178,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
171178
// FIXME(negative_bounds): Handle this correctly...
172179
let trait_ref =
173180
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
174-
needed_associated_types.extend(
181+
ordered_associated_types.extend(
175182
tcx.associated_items(pred.trait_ref.def_id)
176183
.in_definition_order()
177184
// We only care about associated types.
178185
.filter(|item| item.kind == ty::AssocKind::Type)
179186
// No RPITITs -- they're not dyn-compatible for now.
180187
.filter(|item| !item.is_impl_trait_in_trait())
181-
// If the associated type has a `where Self: Sized` bound,
182-
// we do not need to constrain the associated type.
183-
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
184188
.map(|item| (item.def_id, trait_ref)),
185189
);
186190
}
@@ -252,14 +256,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
252256
}
253257
}
254258

259+
// We compute the list of projection bounds taking the ordered associated types,
260+
// and check if there was an entry in the collected `projection_bounds`. Those
261+
// are computed by first taking the user-written associated types, then elaborating
262+
// the principal trait ref, and only using those if there was no user-written.
263+
// See note below about how we handle missing associated types with `Self: Sized`,
264+
// which are not required to be provided, but are still used if they are provided.
255265
let mut missing_assoc_types = FxIndexSet::default();
256-
let projection_bounds: Vec<_> = needed_associated_types
266+
let projection_bounds: Vec<_> = ordered_associated_types
257267
.into_iter()
258268
.filter_map(|key| {
259269
if let Some(assoc) = projection_bounds.get(&key) {
260270
Some(*assoc)
261271
} else {
262-
missing_assoc_types.insert(key);
272+
// If the associated type has a `where Self: Sized` bound, then
273+
// we do not need to provide the associated type. This results in
274+
// a `dyn Trait` type that has a different number of projection
275+
// bounds, which may lead to type mismatches.
276+
if !tcx.generics_require_sized_self(key.0) {
277+
missing_assoc_types.insert(key);
278+
}
263279
None
264280
}
265281
})

compiler/rustc_middle/src/ty/sty.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,10 @@ impl<'tcx> Ty<'tcx> {
720720
repr: DynKind,
721721
) -> Ty<'tcx> {
722722
if cfg!(debug_assertions) {
723-
let projection_count = obj.projection_bounds().count();
723+
let projection_count = obj
724+
.projection_bounds()
725+
.filter(|item| !tcx.generics_require_sized_self(item.item_def_id()))
726+
.count();
724727
let expected_count: usize = obj
725728
.principal_def_id()
726729
.into_iter()

src/ci/channel

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
beta
1+
stable

src/tools/clippy/clippy_lints/src/entry.rs

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -95,14 +95,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
9595
return;
9696
};
9797

98-
if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
99-
span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
100-
return;
101-
}
102-
10398
if then_search.edits.is_empty() && else_search.edits.is_empty() {
10499
// No insertions
105100
return;
101+
} else if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
102+
// If there are other uses of the key, and the key is not copy,
103+
// we cannot perform a fix automatically, but continue to emit a lint.
104+
None
106105
} else if then_search.edits.is_empty() || else_search.edits.is_empty() {
107106
// if .. { insert } else { .. } or if .. { .. } else { insert }
108107
let ((then_str, entry_kind), else_str) = match (else_search.edits.is_empty(), contains_expr.negated) {
@@ -123,10 +122,10 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
123122
snippet_with_applicability(cx, then_expr.span, "{ .. }", &mut app),
124123
),
125124
};
126-
format!(
125+
Some(format!(
127126
"if let {}::{entry_kind} = {map_str}.entry({key_str}) {then_str} else {else_str}",
128127
map_ty.entry_path(),
129-
)
128+
))
130129
} else {
131130
// if .. { insert } else { insert }
132131
let ((then_str, then_entry), (else_str, else_entry)) = if contains_expr.negated {
@@ -142,13 +141,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
142141
};
143142
let indent_str = snippet_indent(cx, expr.span);
144143
let indent_str = indent_str.as_deref().unwrap_or("");
145-
format!(
144+
Some(format!(
146145
"match {map_str}.entry({key_str}) {{\n{indent_str} {entry}::{then_entry} => {}\n\
147146
{indent_str} {entry}::{else_entry} => {}\n{indent_str}}}",
148147
reindent_multiline(&then_str, true, Some(4 + indent_str.len())),
149148
reindent_multiline(&else_str, true, Some(4 + indent_str.len())),
150149
entry = map_ty.entry_path(),
151-
)
150+
))
152151
}
153152
} else {
154153
if then_search.edits.is_empty() {
@@ -163,17 +162,17 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
163162
} else {
164163
then_search.snippet_occupied(cx, then_expr.span, &mut app)
165164
};
166-
format!(
165+
Some(format!(
167166
"if let {}::{entry_kind} = {map_str}.entry({key_str}) {body_str}",
168167
map_ty.entry_path(),
169-
)
168+
))
170169
} else if let Some(insertion) = then_search.as_single_insertion() {
171170
let value_str = snippet_with_context(cx, insertion.value.span, then_expr.span.ctxt(), "..", &mut app).0;
172171
if contains_expr.negated {
173172
if insertion.value.can_have_side_effects() {
174-
format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});")
173+
Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});"))
175174
} else {
176-
format!("{map_str}.entry({key_str}).or_insert({value_str});")
175+
Some(format!("{map_str}.entry({key_str}).or_insert({value_str});"))
177176
}
178177
} else {
179178
// TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
@@ -183,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
183182
} else {
184183
let block_str = then_search.snippet_closure(cx, then_expr.span, &mut app);
185184
if contains_expr.negated {
186-
format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});")
185+
Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});"))
187186
} else {
188187
// TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
189188
// This would need to be a different lint.
@@ -192,7 +191,11 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
192191
}
193192
};
194193

195-
span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
194+
if let Some(sugg) = sugg {
195+
span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
196+
} else {
197+
span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
198+
}
196199
}
197200
}
198201

src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool
8585
/// contains `Err(IDENT)`, `None` otherwise.
8686
fn is_ok_or_err<'hir>(cx: &LateContext<'_>, pat: &Pat<'hir>) -> Option<(bool, &'hir Ident)> {
8787
if let PatKind::TupleStruct(qpath, [arg], _) = &pat.kind
88-
&& let PatKind::Binding(BindingMode::NONE, _, ident, _) = &arg.kind
88+
&& let PatKind::Binding(BindingMode::NONE, _, ident, None) = &arg.kind
8989
&& let res = cx.qpath_res(qpath, pat.hir_id)
9090
&& let Res::Def(DefKind::Ctor(..), id) = res
9191
&& let id @ Some(_) = cx.tcx.opt_parent(id)

src/tools/clippy/clippy_lints/src/ptr.rs

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -786,9 +786,9 @@ fn check_ptr_eq<'tcx>(
786786
}
787787

788788
// Remove one level of usize conversion if any
789-
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
790-
(Some(lhs), Some(rhs)) => (lhs, rhs),
791-
_ => (left, right),
789+
let (left, right, usize_peeled) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
790+
(Some(lhs), Some(rhs)) => (lhs, rhs, true),
791+
_ => (left, right, false),
792792
};
793793

794794
// This lint concerns raw pointers
@@ -797,10 +797,16 @@ fn check_ptr_eq<'tcx>(
797797
return;
798798
}
799799

800-
let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
800+
let ((left_var, left_casts_peeled), (right_var, right_casts_peeled)) =
801+
(peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
801802

802-
if let Some(left_snip) = left_var.span.get_source_text(cx)
803-
&& let Some(right_snip) = right_var.span.get_source_text(cx)
803+
if !(usize_peeled || left_casts_peeled || right_casts_peeled) {
804+
return;
805+
}
806+
807+
let mut app = Applicability::MachineApplicable;
808+
let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
809+
let right_snip = Sugg::hir_with_context(cx, right_var, expr.span.ctxt(), "_", &mut app);
804810
{
805811
let Some(top_crate) = std_or_core(cx) else { return };
806812
let invert = if op == BinOpKind::Eq { "" } else { "!" };
@@ -811,15 +817,16 @@ fn check_ptr_eq<'tcx>(
811817
format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
812818
"try",
813819
format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"),
814-
Applicability::MachineApplicable,
820+
app,
815821
);
816822
}
817823
}
818824

819825
// If the given expression is a cast to a usize, return the lhs of the cast
820826
// E.g., `foo as *const _ as usize` returns `foo as *const _`.
821827
fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
822-
if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
828+
if !cast_expr.span.from_expansion()
829+
&& cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
823830
&& let ExprKind::Cast(expr, _) = cast_expr.kind
824831
{
825832
Some(expr)
@@ -828,16 +835,18 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
828835
}
829836
}
830837

831-
// Peel raw casts if the remaining expression can be coerced to it
832-
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
833-
if let ExprKind::Cast(inner, _) = expr.kind
838+
// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
839+
// peeled or not.
840+
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
841+
if !expr.span.from_expansion()
842+
&& let ExprKind::Cast(inner, _) = expr.kind
834843
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
835844
&& let inner_ty = cx.typeck_results().expr_ty(inner)
836845
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
837846
&& target_ty == inner_target_ty
838847
{
839-
peel_raw_casts(cx, inner, inner_ty)
848+
(peel_raw_casts(cx, inner, inner_ty).0, true)
840849
} else {
841-
expr
850+
(expr, false)
842851
}
843852
}

src/tools/clippy/tests/ui/entry.fixed

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,4 +226,26 @@ fn issue11976() {
226226
}
227227
}
228228

229+
mod issue14449 {
230+
use std::collections::BTreeMap;
231+
232+
pub struct Meow {
233+
map: BTreeMap<String, String>,
234+
}
235+
236+
impl Meow {
237+
fn pet(&self, _key: &str, _v: u32) -> u32 {
238+
42
239+
}
240+
}
241+
242+
pub fn f(meow: &Meow, x: String) {
243+
if meow.map.contains_key(&x) {
244+
let _ = meow.pet(&x, 1);
245+
} else {
246+
let _ = meow.pet(&x, 0);
247+
}
248+
}
249+
}
250+
229251
fn main() {}

src/tools/clippy/tests/ui/entry.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,4 +232,26 @@ fn issue11976() {
232232
}
233233
}
234234

235+
mod issue14449 {
236+
use std::collections::BTreeMap;
237+
238+
pub struct Meow {
239+
map: BTreeMap<String, String>,
240+
}
241+
242+
impl Meow {
243+
fn pet(&self, _key: &str, _v: u32) -> u32 {
244+
42
245+
}
246+
}
247+
248+
pub fn f(meow: &Meow, x: String) {
249+
if meow.map.contains_key(&x) {
250+
let _ = meow.pet(&x, 1);
251+
} else {
252+
let _ = meow.pet(&x, 0);
253+
}
254+
}
255+
}
256+
235257
fn main() {}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy