Skip to content

Commit 4e1356b

Browse files
committed
Auto merge of rust-lang#137290 - matthiaskrgr:rollup-a7xdbi4, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - rust-lang#120580 (Add `MAX_LEN_UTF8` and `MAX_LEN_UTF16` Constants) - rust-lang#132268 (Impl TryFrom<Vec<u8>> for String) - rust-lang#136093 (Match Ergonomics 2024: update old-edition behavior of feature gates) - rust-lang#136344 (Suggest replacing `.` with `::` in more error diagnostics.) - rust-lang#136690 (Use more explicit and reliable ptr select in sort impls) - rust-lang#136815 (CI: Stop /msys64/bin from being prepended to PATH in msys2 shell) - rust-lang#136923 (Lint `#[must_use]` attributes applied to methods in trait impls) - rust-lang#137155 (Organize `OsString`/`OsStr` shims) r? `@ghost` `@rustbot` modify labels: rollup
2 parents f280acf + 3964bb1 commit 4e1356b

File tree

83 files changed

+2896
-934
lines changed

Some content is hidden

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

83 files changed

+2896
-934
lines changed

.github/workflows/ci.yml

+5
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,11 @@ jobs:
173173
- name: ensure the stable version number is correct
174174
run: src/ci/scripts/verify-stable-version-number.sh
175175

176+
# Show the environment just before we run the build
177+
# This makes it easier to diagnose problems with the above install scripts.
178+
- name: show the current environment
179+
run: src/ci/scripts/dump-environment.sh
180+
176181
- name: run the build
177182
# Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
178183
run: src/ci/scripts/run-build-from-ci.sh 2>&1

compiler/rustc_hir_typeck/src/pat.rs

+60-7
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,19 @@ enum InheritedRefMatchRule {
230230
/// underlying type is not a reference type, the inherited reference will be consumed.
231231
EatInner,
232232
/// When the underlying type is a reference type, reference patterns consume both layers of
233-
/// reference, i.e. they both reset the binding mode and consume the reference type. Reference
234-
/// patterns are not permitted when there is no underlying reference type, i.e. they can't eat
235-
/// only an inherited reference. This is the current stable Rust behavior.
236-
EatBoth,
233+
/// reference, i.e. they both reset the binding mode and consume the reference type.
234+
EatBoth {
235+
/// If `true`, an inherited reference will be considered when determining whether a reference
236+
/// pattern matches a given type:
237+
/// - If the underlying type is not a reference, a reference pattern may eat the inherited reference;
238+
/// - If the underlying type is a reference, a reference pattern matches if it can eat either one
239+
/// of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the
240+
/// underlying type is `&mut` or the inherited reference is `&mut`.
241+
/// If `false`, a reference pattern is only matched against the underlying type.
242+
/// This is `false` for stable Rust and `true` for both the `ref_pat_eat_one_layer_2024` and
243+
/// `ref_pat_eat_one_layer_2024_structural` feature gates.
244+
consider_inherited_ref: bool,
245+
},
237246
}
238247

239248
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -259,10 +268,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259268
} else {
260269
// Currently, matching against an inherited ref on edition 2024 is an error.
261270
// Use `EatBoth` as a fallback to be similar to stable Rust.
262-
InheritedRefMatchRule::EatBoth
271+
InheritedRefMatchRule::EatBoth { consider_inherited_ref: false }
263272
}
264273
} else {
265-
InheritedRefMatchRule::EatBoth
274+
InheritedRefMatchRule::EatBoth {
275+
consider_inherited_ref: self.tcx.features().ref_pat_eat_one_layer_2024()
276+
|| self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
277+
}
266278
}
267279
}
268280

@@ -2371,6 +2383,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23712383
// NB: This assumes that `&` patterns can match against mutable
23722384
// references (RFC 3627, Rule 5). If we implement a pattern typing
23732385
// ruleset with Rule 4 but not Rule 5, we'll need to check that here.
2386+
// FIXME(ref_pat_eat_one_layer_2024_structural): If we already tried
2387+
// matching the real reference, the error message should explain that
2388+
// falling back to the inherited reference didn't work. This should be
2389+
// the same error as the old-Edition version below.
23742390
debug_assert!(ref_pat_matches_mut_ref);
23752391
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
23762392
}
@@ -2381,9 +2397,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23812397
return expected;
23822398
}
23832399
}
2384-
InheritedRefMatchRule::EatBoth => {
2400+
InheritedRefMatchRule::EatBoth { consider_inherited_ref: true } => {
23852401
// Reset binding mode on old editions
23862402
pat_info.binding_mode = ByRef::No;
2403+
2404+
if let ty::Ref(_, inner_ty, _) = *expected.kind() {
2405+
// Consume both the inherited and inner references.
2406+
if pat_mutbl.is_mut() && inh_mut.is_mut() {
2407+
// As a special case, a `&mut` reference pattern will be able to match
2408+
// against a reference type of any mutability if the inherited ref is
2409+
// mutable. Since this allows us to match against a shared reference
2410+
// type, we refer to this as "falling back" to matching the inherited
2411+
// reference, though we consume the real reference as well. We handle
2412+
// this here to avoid adding this case to the common logic below.
2413+
self.check_pat(inner, inner_ty, pat_info);
2414+
return expected;
2415+
} else {
2416+
// Otherwise, use the common logic below for matching the inner
2417+
// reference type.
2418+
// FIXME(ref_pat_eat_one_layer_2024_structural): If this results in a
2419+
// mutability mismatch, the error message should explain that falling
2420+
// back to the inherited reference didn't work. This should be the same
2421+
// error as the Edition 2024 version above.
2422+
}
2423+
} else {
2424+
// The expected type isn't a reference type, so only match against the
2425+
// inherited reference.
2426+
if pat_mutbl > inh_mut {
2427+
// We can't match a lone inherited shared reference with `&mut`.
2428+
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2429+
}
2430+
2431+
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2432+
self.check_pat(inner, expected, pat_info);
2433+
return expected;
2434+
}
2435+
}
2436+
InheritedRefMatchRule::EatBoth { consider_inherited_ref: false } => {
2437+
// Reset binding mode on stable Rust. This will be a type error below if
2438+
// `expected` is not a reference type.
2439+
pat_info.binding_mode = ByRef::No;
23872440
self.add_rust_2024_migration_desugared_pat(
23882441
pat_info.top_info.hir_id,
23892442
pat,

compiler/rustc_passes/src/check_attr.rs

+29-18
Original file line numberDiff line numberDiff line change
@@ -1431,37 +1431,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
14311431

14321432
/// Warns against some misuses of `#[must_use]`
14331433
fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
1434-
if !matches!(
1434+
if matches!(
14351435
target,
14361436
Target::Fn
14371437
| Target::Enum
14381438
| Target::Struct
14391439
| Target::Union
1440-
| Target::Method(_)
1440+
| Target::Method(MethodKind::Trait { body: false } | MethodKind::Inherent)
14411441
| Target::ForeignFn
14421442
// `impl Trait` in return position can trip
14431443
// `unused_must_use` if `Trait` is marked as
14441444
// `#[must_use]`
14451445
| Target::Trait
14461446
) {
1447-
let article = match target {
1448-
Target::ExternCrate
1449-
| Target::Enum
1450-
| Target::Impl
1451-
| Target::Expression
1452-
| Target::Arm
1453-
| Target::AssocConst
1454-
| Target::AssocTy => "an",
1455-
_ => "a",
1456-
};
1447+
return;
1448+
}
14571449

1458-
self.tcx.emit_node_span_lint(
1459-
UNUSED_ATTRIBUTES,
1460-
hir_id,
1461-
attr.span,
1462-
errors::MustUseNoEffect { article, target },
1463-
);
1450+
// `#[must_use]` can be applied to a trait method definition with a default body
1451+
if let Target::Method(MethodKind::Trait { body: true }) = target
1452+
&& let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id
1453+
&& let containing_item = self.tcx.hir().expect_item(parent_def_id)
1454+
&& let hir::ItemKind::Trait(..) = containing_item.kind
1455+
{
1456+
return;
14641457
}
1458+
1459+
let article = match target {
1460+
Target::ExternCrate
1461+
| Target::Enum
1462+
| Target::Impl
1463+
| Target::Expression
1464+
| Target::Arm
1465+
| Target::AssocConst
1466+
| Target::AssocTy => "an",
1467+
_ => "a",
1468+
};
1469+
1470+
self.tcx.emit_node_span_lint(
1471+
UNUSED_ATTRIBUTES,
1472+
hir_id,
1473+
attr.span,
1474+
errors::MustUseNoEffect { article, target },
1475+
);
14651476
}
14661477

14671478
/// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.

compiler/rustc_resolve/src/late/diagnostics.rs

+64-24
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_ast::ptr::P;
88
use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
99
use rustc_ast::{
1010
self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
11-
Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind,
11+
Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
1212
};
1313
use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
1414
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
@@ -1529,7 +1529,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
15291529
Applicability::MaybeIncorrect,
15301530
);
15311531
true
1532-
} else if kind == DefKind::Struct
1532+
} else if matches!(kind, DefKind::Struct | DefKind::TyAlias)
15331533
&& let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
15341534
&& let Ok(snippet) = this.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
15351535
{
@@ -1566,7 +1566,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
15661566
}
15671567
};
15681568

1569-
let mut bad_struct_syntax_suggestion = |this: &mut Self, def_id: DefId| {
1569+
let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| {
15701570
let (followed_by_brace, closing_brace) = this.followed_by_brace(span);
15711571

15721572
match source {
@@ -1740,12 +1740,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
17401740
}
17411741
}
17421742
(
1743-
Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
1743+
Res::Def(kind @ (DefKind::Mod | DefKind::Trait | DefKind::TyAlias), _),
17441744
PathSource::Expr(Some(parent)),
1745-
) => {
1746-
if !path_sep(self, err, parent, kind) {
1747-
return false;
1748-
}
1745+
) if path_sep(self, err, parent, kind) => {
1746+
return true;
17491747
}
17501748
(
17511749
Res::Def(DefKind::Enum, def_id),
@@ -1777,13 +1775,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
17771775
let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
17781776
if let PathSource::Expr(Some(parent)) = source {
17791777
if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
1780-
bad_struct_syntax_suggestion(self, def_id);
1778+
bad_struct_syntax_suggestion(self, err, def_id);
17811779
return true;
17821780
}
17831781
}
17841782
struct_ctor
17851783
} else {
1786-
bad_struct_syntax_suggestion(self, def_id);
1784+
bad_struct_syntax_suggestion(self, err, def_id);
17871785
return true;
17881786
};
17891787

@@ -1861,7 +1859,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
18611859
err.span_label(span, "constructor is not visible here due to private fields");
18621860
}
18631861
(Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => {
1864-
bad_struct_syntax_suggestion(self, def_id);
1862+
bad_struct_syntax_suggestion(self, err, def_id);
18651863
}
18661864
(Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
18671865
match source {
@@ -2471,31 +2469,73 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
24712469
def_id: DefId,
24722470
span: Span,
24732471
) {
2474-
let Some(variants) = self.collect_enum_ctors(def_id) else {
2472+
let Some(variant_ctors) = self.collect_enum_ctors(def_id) else {
24752473
err.note("you might have meant to use one of the enum's variants");
24762474
return;
24772475
};
24782476

2479-
let suggest_only_tuple_variants =
2480-
matches!(source, PathSource::TupleStruct(..)) || source.is_call();
2481-
if suggest_only_tuple_variants {
2477+
// If the expression is a field-access or method-call, try to find a variant with the field/method name
2478+
// that could have been intended, and suggest replacing the `.` with `::`.
2479+
// Otherwise, suggest adding `::VariantName` after the enum;
2480+
// and if the expression is call-like, only suggest tuple variants.
2481+
let (suggest_path_sep_dot_span, suggest_only_tuple_variants) = match source {
2482+
// `Type(a, b)` in a pattern, only suggest adding a tuple variant after `Type`.
2483+
PathSource::TupleStruct(..) => (None, true),
2484+
PathSource::Expr(Some(expr)) => match &expr.kind {
2485+
// `Type(a, b)`, only suggest adding a tuple variant after `Type`.
2486+
ExprKind::Call(..) => (None, true),
2487+
// `Type.Foo(a, b)`, suggest replacing `.` -> `::` if variant `Foo` exists and is a tuple variant,
2488+
// otherwise suggest adding a variant after `Type`.
2489+
ExprKind::MethodCall(box MethodCall {
2490+
receiver,
2491+
span,
2492+
seg: PathSegment { ident, .. },
2493+
..
2494+
}) => {
2495+
let dot_span = receiver.span.between(*span);
2496+
let found_tuple_variant = variant_ctors.iter().any(|(path, _, ctor_kind)| {
2497+
*ctor_kind == CtorKind::Fn
2498+
&& path.segments.last().is_some_and(|seg| seg.ident == *ident)
2499+
});
2500+
(found_tuple_variant.then_some(dot_span), false)
2501+
}
2502+
// `Type.Foo`, suggest replacing `.` -> `::` if variant `Foo` exists and is a unit or tuple variant,
2503+
// otherwise suggest adding a variant after `Type`.
2504+
ExprKind::Field(base, ident) => {
2505+
let dot_span = base.span.between(ident.span);
2506+
let found_tuple_or_unit_variant = variant_ctors.iter().any(|(path, ..)| {
2507+
path.segments.last().is_some_and(|seg| seg.ident == *ident)
2508+
});
2509+
(found_tuple_or_unit_variant.then_some(dot_span), false)
2510+
}
2511+
_ => (None, false),
2512+
},
2513+
_ => (None, false),
2514+
};
2515+
2516+
if let Some(dot_span) = suggest_path_sep_dot_span {
2517+
err.span_suggestion_verbose(
2518+
dot_span,
2519+
"use the path separator to refer to a variant",
2520+
"::",
2521+
Applicability::MaybeIncorrect,
2522+
);
2523+
} else if suggest_only_tuple_variants {
24822524
// Suggest only tuple variants regardless of whether they have fields and do not
24832525
// suggest path with added parentheses.
2484-
let mut suggestable_variants = variants
2526+
let mut suggestable_variants = variant_ctors
24852527
.iter()
24862528
.filter(|(.., kind)| *kind == CtorKind::Fn)
24872529
.map(|(variant, ..)| path_names_to_string(variant))
24882530
.collect::<Vec<_>>();
24892531
suggestable_variants.sort();
24902532

2491-
let non_suggestable_variant_count = variants.len() - suggestable_variants.len();
2533+
let non_suggestable_variant_count = variant_ctors.len() - suggestable_variants.len();
24922534

2493-
let source_msg = if source.is_call() {
2494-
"to construct"
2495-
} else if matches!(source, PathSource::TupleStruct(..)) {
2535+
let source_msg = if matches!(source, PathSource::TupleStruct(..)) {
24962536
"to match against"
24972537
} else {
2498-
unreachable!()
2538+
"to construct"
24992539
};
25002540

25012541
if !suggestable_variants.is_empty() {
@@ -2514,7 +2554,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
25142554
}
25152555

25162556
// If the enum has no tuple variants..
2517-
if non_suggestable_variant_count == variants.len() {
2557+
if non_suggestable_variant_count == variant_ctors.len() {
25182558
err.help(format!("the enum has no tuple variants {source_msg}"));
25192559
}
25202560

@@ -2537,7 +2577,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
25372577
}
25382578
};
25392579

2540-
let mut suggestable_variants = variants
2580+
let mut suggestable_variants = variant_ctors
25412581
.iter()
25422582
.filter(|(_, def_id, kind)| !needs_placeholder(*def_id, *kind))
25432583
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))
@@ -2564,7 +2604,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
25642604
);
25652605
}
25662606

2567-
let mut suggestable_variants_with_placeholders = variants
2607+
let mut suggestable_variants_with_placeholders = variant_ctors
25682608
.iter()
25692609
.filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
25702610
.map(|(variant, _, kind)| (path_names_to_string(variant), kind))

library/alloc/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
#![feature(box_uninit_write)]
106106
#![feature(bstr)]
107107
#![feature(bstr_internals)]
108+
#![feature(char_max_len)]
108109
#![feature(clone_to_uninit)]
109110
#![feature(coerce_unsized)]
110111
#![feature(const_eval_select)]

0 commit comments

Comments
 (0)