Skip to content

Commit b4591cb

Browse files
committed
Auto merge of #113188 - matthiaskrgr:rollup-j3abaks, r=matthiaskrgr
Rollup of 6 pull requests Successful merges: - #107624 (Stabilize `const_cstr_methods`) - #111403 (suggest `slice::swap` for `mem::swap(&mut x[0], &mut x[1])` borrowck error) - #113071 (Account for late-bound vars from parent arg-position impl trait) - #113165 (Encode item bounds for `DefKind::ImplTraitPlaceholder`) - #113171 (Properly implement variances_of for RPITIT GAT) - #113177 (Use structured suggestion when telling user about `for<'a>`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 97279e9 + 207b244 commit b4591cb

32 files changed

+327
-99
lines changed

Diff for: compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -982,7 +982,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
982982
&msg_borrow,
983983
None,
984984
);
985-
self.suggest_split_at_mut_if_applicable(
985+
self.suggest_slice_method_if_applicable(
986986
&mut err,
987987
place,
988988
issued_borrow.borrowed_place,
@@ -1262,7 +1262,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12621262
);
12631263
}
12641264

1265-
fn suggest_split_at_mut_if_applicable(
1265+
fn suggest_slice_method_if_applicable(
12661266
&self,
12671267
err: &mut Diagnostic,
12681268
place: Place<'tcx>,
@@ -1274,7 +1274,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
12741274
err.help(
12751275
"consider using `.split_at_mut(position)` or similar method to obtain \
12761276
two mutable non-overlapping sub-slices",
1277-
);
1277+
)
1278+
.help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
12781279
}
12791280
}
12801281

Diff for: compiler/rustc_hir_analysis/messages.ftl

+9
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ hir_analysis_invalid_union_field =
9999
hir_analysis_invalid_union_field_sugg =
100100
wrap the field type in `ManuallyDrop<...>`
101101
102+
hir_analysis_late_bound_const_in_apit = `impl Trait` can only mention const parameters from an fn or impl
103+
.label = const parameter declared here
104+
105+
hir_analysis_late_bound_lifetime_in_apit = `impl Trait` can only mention lifetimes from an fn or impl
106+
.label = lifetime declared here
107+
108+
hir_analysis_late_bound_type_in_apit = `impl Trait` can only mention type parameters from an fn or impl
109+
.label = type parameter declared here
110+
102111
hir_analysis_lifetimes_or_bounds_mismatch_on_trait =
103112
lifetime parameters or bounds on {$item_kind} `{$ident}` do not match the trait declaration
104113
.label = lifetimes do not match {$item_kind} in trait

Diff for: compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs

+49-6
Original file line numberDiff line numberDiff line change
@@ -1344,12 +1344,10 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13441344
Scope::Binder {
13451345
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
13461346
} => {
1347-
let mut err = self.tcx.sess.struct_span_err(
1348-
lifetime_ref.ident.span,
1349-
"`impl Trait` can only mention lifetimes bound at the fn or impl level",
1350-
);
1351-
err.span_note(self.tcx.def_span(region_def_id), "lifetime declared here");
1352-
err.emit();
1347+
self.tcx.sess.emit_err(errors::LateBoundInApit::Lifetime {
1348+
span: lifetime_ref.ident.span,
1349+
param_span: self.tcx.def_span(region_def_id),
1350+
});
13531351
return;
13541352
}
13551353
Scope::Root { .. } => break,
@@ -1379,6 +1377,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
13791377
let mut late_depth = 0;
13801378
let mut scope = self.scope;
13811379
let mut crossed_anon_const = false;
1380+
13821381
let result = loop {
13831382
match *scope {
13841383
Scope::Body { s, .. } => {
@@ -1446,6 +1445,50 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
14461445
return;
14471446
}
14481447

1448+
// We may fail to resolve higher-ranked ty/const vars that are mentioned by APIT.
1449+
// AST-based resolution does not care for impl-trait desugaring, which are the
1450+
// responsibility of lowering. This may create a mismatch between the resolution
1451+
// AST found (`param_def_id`) which points to HRTB, and what HIR allows.
1452+
// ```
1453+
// fn foo(x: impl for<T> Trait<Assoc = impl Trait2<T>>) {}
1454+
// ```
1455+
//
1456+
// In such case, walk back the binders to diagnose it properly.
1457+
let mut scope = self.scope;
1458+
loop {
1459+
match *scope {
1460+
Scope::Binder {
1461+
where_bound_origin: Some(hir::PredicateOrigin::ImplTrait), ..
1462+
} => {
1463+
let guar = self.tcx.sess.emit_err(match self.tcx.def_kind(param_def_id) {
1464+
DefKind::TyParam => errors::LateBoundInApit::Type {
1465+
span: self.tcx.hir().span(hir_id),
1466+
param_span: self.tcx.def_span(param_def_id),
1467+
},
1468+
DefKind::ConstParam => errors::LateBoundInApit::Const {
1469+
span: self.tcx.hir().span(hir_id),
1470+
param_span: self.tcx.def_span(param_def_id),
1471+
},
1472+
kind => {
1473+
bug!("unexpected def-kind: {}", kind.descr(param_def_id.to_def_id()))
1474+
}
1475+
});
1476+
self.map.defs.insert(hir_id, ResolvedArg::Error(guar));
1477+
return;
1478+
}
1479+
Scope::Root { .. } => break,
1480+
Scope::Binder { s, .. }
1481+
| Scope::Body { s, .. }
1482+
| Scope::Elision { s, .. }
1483+
| Scope::ObjectLifetimeDefault { s, .. }
1484+
| Scope::Supertrait { s, .. }
1485+
| Scope::TraitRefBoundary { s, .. }
1486+
| Scope::AnonConstBoundary { s } => {
1487+
scope = s;
1488+
}
1489+
}
1490+
}
1491+
14491492
self.tcx.sess.delay_span_bug(
14501493
self.tcx.hir().span(hir_id),
14511494
format!("could not resolve {param_def_id:?}"),

Diff for: compiler/rustc_hir_analysis/src/errors.rs

+25
Original file line numberDiff line numberDiff line change
@@ -875,3 +875,28 @@ pub(crate) enum ReturnTypeNotationIllegalParam {
875875
param_span: Span,
876876
},
877877
}
878+
879+
#[derive(Diagnostic)]
880+
pub(crate) enum LateBoundInApit {
881+
#[diag(hir_analysis_late_bound_type_in_apit)]
882+
Type {
883+
#[primary_span]
884+
span: Span,
885+
#[label]
886+
param_span: Span,
887+
},
888+
#[diag(hir_analysis_late_bound_const_in_apit)]
889+
Const {
890+
#[primary_span]
891+
span: Span,
892+
#[label]
893+
param_span: Span,
894+
},
895+
#[diag(hir_analysis_late_bound_lifetime_in_apit)]
896+
Lifetime {
897+
#[primary_span]
898+
span: Span,
899+
#[label]
900+
param_span: Span,
901+
},
902+
}

Diff for: compiler/rustc_hir_analysis/src/variance/mod.rs

+15-9
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
77
use rustc_hir::def::DefKind;
88
use rustc_hir::def_id::{DefId, LocalDefId};
99
use rustc_middle::query::Providers;
10-
use rustc_middle::ty::{self, CrateVariancesMap, SubstsRef, Ty, TyCtxt};
10+
use rustc_middle::ty::{self, CrateVariancesMap, ImplTraitInTraitData, SubstsRef, Ty, TyCtxt};
1111
use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable};
1212
use std::ops::ControlFlow;
1313

@@ -51,20 +51,26 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
5151
| DefKind::Struct
5252
| DefKind::Union
5353
| DefKind::Variant
54-
| DefKind::Ctor(..) => {}
54+
| DefKind::Ctor(..) => {
55+
// These are inferred.
56+
let crate_map = tcx.crate_variances(());
57+
return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
58+
}
5559
DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
5660
return variance_of_opaque(tcx, item_def_id);
5761
}
58-
_ => {
59-
// Variance not relevant.
60-
span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item")
62+
DefKind::AssocTy => {
63+
if let Some(ImplTraitInTraitData::Trait { .. }) =
64+
tcx.opt_rpitit_info(item_def_id.to_def_id())
65+
{
66+
return variance_of_opaque(tcx, item_def_id);
67+
}
6168
}
69+
_ => {}
6270
}
6371

64-
// Everything else must be inferred.
65-
66-
let crate_map = tcx.crate_variances(());
67-
crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[])
72+
// Variance not relevant.
73+
span_bug!(tcx.def_span(item_def_id), "asked to compute variance for wrong kind of item");
6874
}
6975

7076
#[instrument(level = "trace", skip(tcx), ret)]

Diff for: compiler/rustc_metadata/src/rmeta/encoder.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1447,6 +1447,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14471447
.is_type_alias_impl_trait
14481448
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
14491449
}
1450+
if let DefKind::ImplTraitPlaceholder = def_kind {
1451+
self.encode_explicit_item_bounds(def_id);
1452+
}
14501453
if tcx.impl_method_has_trait_impl_trait_tys(def_id)
14511454
&& let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
14521455
{

Diff for: compiler/rustc_resolve/src/late.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -1632,9 +1632,13 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
16321632
..
16331633
} = &rib.kind
16341634
{
1635-
diag.span_help(
1636-
*span,
1637-
"consider introducing a higher-ranked lifetime here with `for<'a>`",
1635+
diag.multipart_suggestion(
1636+
"consider introducing a higher-ranked lifetime here",
1637+
vec![
1638+
(span.shrink_to_lo(), "for<'a> ".into()),
1639+
(lifetime.ident.span.shrink_to_hi(), "'a ".into()),
1640+
],
1641+
Applicability::MachineApplicable,
16381642
);
16391643
break;
16401644
}

Diff for: library/core/src/ffi/c_str.rs

+10-7
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ impl CStr {
241241
/// ```
242242
///
243243
/// ```
244-
/// #![feature(const_cstr_methods)]
244+
/// #![feature(const_cstr_from_ptr)]
245245
///
246246
/// use std::ffi::{c_char, CStr};
247247
///
@@ -256,7 +256,7 @@ impl CStr {
256256
#[inline]
257257
#[must_use]
258258
#[stable(feature = "rust1", since = "1.0.0")]
259-
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
259+
#[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "101719")]
260260
pub const unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
261261
// SAFETY: The caller has provided a pointer that points to a valid C
262262
// string with a NUL terminator of size less than `isize::MAX`, whose
@@ -377,7 +377,7 @@ impl CStr {
377377
/// assert!(cstr.is_err());
378378
/// ```
379379
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
380-
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
380+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
381381
pub const fn from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError> {
382382
let nul_pos = memchr::memchr(0, bytes);
383383
match nul_pos {
@@ -561,10 +561,12 @@ impl CStr {
561561
#[must_use = "this returns the result of the operation, \
562562
without modifying the original"]
563563
#[stable(feature = "rust1", since = "1.0.0")]
564-
pub fn to_bytes(&self) -> &[u8] {
564+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
565+
pub const fn to_bytes(&self) -> &[u8] {
565566
let bytes = self.to_bytes_with_nul();
567+
// FIXME(const-hack) replace with range index
566568
// SAFETY: to_bytes_with_nul returns slice with length at least 1
567-
unsafe { bytes.get_unchecked(..bytes.len() - 1) }
569+
unsafe { slice::from_raw_parts(bytes.as_ptr(), bytes.len() - 1) }
568570
}
569571

570572
/// Converts this C string to a byte slice containing the trailing 0 byte.
@@ -588,7 +590,7 @@ impl CStr {
588590
#[must_use = "this returns the result of the operation, \
589591
without modifying the original"]
590592
#[stable(feature = "rust1", since = "1.0.0")]
591-
#[rustc_const_unstable(feature = "const_cstr_methods", issue = "101719")]
593+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
592594
pub const fn to_bytes_with_nul(&self) -> &[u8] {
593595
// SAFETY: Transmuting a slice of `c_char`s to a slice of `u8`s
594596
// is safe on all supported targets.
@@ -612,7 +614,8 @@ impl CStr {
612614
/// assert_eq!(cstr.to_str(), Ok("foo"));
613615
/// ```
614616
#[stable(feature = "cstr_to_str", since = "1.4.0")]
615-
pub fn to_str(&self) -> Result<&str, str::Utf8Error> {
617+
#[rustc_const_stable(feature = "const_cstr_methods", since = "CURRENT_RUSTC_VERSION")]
618+
pub const fn to_str(&self) -> Result<&str, str::Utf8Error> {
616619
// N.B., when `CStr` is changed to perform the length check in `.to_bytes()`
617620
// instead of in `from_ptr()`, it may be worth considering if this should
618621
// be rewritten to do the UTF-8 check inline with the length calculation

Diff for: library/core/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,6 @@
113113
#![feature(const_caller_location)]
114114
#![feature(const_cell_into_inner)]
115115
#![feature(const_char_from_u32_unchecked)]
116-
#![feature(const_cstr_methods)]
117116
#![feature(const_discriminant)]
118117
#![feature(const_eval_select)]
119118
#![feature(const_exact_div)]

Diff for: tests/ui/error-codes/E0637.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
2222
LL | T: Into<&u32>,
2323
| ^ explicit lifetime name needed here
2424
|
25-
help: consider introducing a higher-ranked lifetime here with `for<'a>`
26-
--> $DIR/E0637.rs:13:8
25+
help: consider introducing a higher-ranked lifetime here
2726
|
28-
LL | T: Into<&u32>,
29-
| ^
27+
LL | T: for<'a> Into<&'a u32>,
28+
| +++++++ ++
3029

3130
error: aborting due to 3 previous errors
3231

Diff for: tests/ui/generics/issue-65285-incorrect-explicit-lifetime-name-needed.stderr

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here
44
LL | fn should_error<T>() where T : Into<&u32> {}
55
| ^ explicit lifetime name needed here
66
|
7-
help: consider introducing a higher-ranked lifetime here with `for<'a>`
8-
--> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:5:32
7+
help: consider introducing a higher-ranked lifetime here
98
|
10-
LL | fn should_error<T>() where T : Into<&u32> {}
11-
| ^
9+
LL | fn should_error<T>() where T : for<'a> Into<&'a u32> {}
10+
| +++++++ ++
1211

1312
error[E0106]: missing lifetime specifier
1413
--> $DIR/issue-65285-incorrect-explicit-lifetime-name-needed.rs:9:20

Diff for: tests/ui/impl-trait/in-trait/foreign.rs

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ impl Foo for Local {
1414
fn bar(self) -> Arc<String> { Arc::new(String::new()) }
1515
}
1616

17+
fn generic(f: impl Foo) {
18+
let x = &*f.bar();
19+
}
20+
1721
fn main() {
1822
// Witness an RPITIT from another crate.
1923
let &() = Foreign.bar();

Diff for: tests/ui/impl-trait/in-trait/variances-of-gat.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
3+
// revisions: current next
4+
5+
#![feature(return_position_impl_trait_in_trait)]
6+
7+
trait Foo {}
8+
9+
impl Foo for () {}
10+
11+
trait ThreeCellFragment {
12+
fn ext_cells<'a>(&'a self) -> impl Foo + 'a {
13+
self.ext_adjacent_cells()
14+
}
15+
16+
fn ext_adjacent_cells<'a>(&'a self) -> impl Foo + 'a;
17+
}
18+
19+
fn main() {}

Diff for: tests/ui/impl-trait/universal_wrong_hrtb.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ trait Trait<'a> {
33
}
44

55
fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
6-
//~^ ERROR `impl Trait` can only mention lifetimes bound at the fn or impl level
6+
//~^ ERROR `impl Trait` can only mention lifetimes from an fn or impl
77

88
fn main() {}

Diff for: tests/ui/impl-trait/universal_wrong_hrtb.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
error: `impl Trait` can only mention lifetimes bound at the fn or impl level
1+
error: `impl Trait` can only mention lifetimes from an fn or impl
22
--> $DIR/universal_wrong_hrtb.rs:5:73
33
|
44
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
5-
| ^^
6-
|
7-
note: lifetime declared here
8-
--> $DIR/universal_wrong_hrtb.rs:5:39
9-
|
10-
LL | fn test_argument_position(x: impl for<'a> Trait<'a, Assoc = impl Copy + 'a>) {}
11-
| ^^
5+
| -- lifetime declared here ^^
126

137
error: aborting due to previous error
148

Diff for: tests/ui/suggestions/suggest-split-at-mut.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ LL | *a = 5;
99
| ------ first borrow later used here
1010
|
1111
= help: consider using `.split_at_mut(position)` or similar method to obtain two mutable non-overlapping sub-slices
12+
= help: consider using `.swap(index_1, index_2)` to swap elements at the specified indices
1213

1314
error: aborting due to previous error
1415

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#![feature(non_lifetime_binders)]
2+
//~^ WARN the feature `non_lifetime_binders` is incomplete
3+
4+
trait Trait<Input> {
5+
type Assoc;
6+
}
7+
8+
fn uwu(_: impl for<T> Trait<(), Assoc = impl Trait<T>>) {}
9+
//~^ ERROR `impl Trait` can only mention type parameters from an fn or impl
10+
11+
fn main() {}

0 commit comments

Comments
 (0)