Skip to content

Commit 837bf37

Browse files
committed
Auto merge of rust-lang#102388 - JohnTitor:rollup-mbyw6fl, r=JohnTitor
Rollup of 8 pull requests Successful merges: - rust-lang#100747 (Add long description and test for E0311) - rust-lang#102232 (Stabilize bench_black_box) - rust-lang#102288 (Suggest unwrapping `???<T>` if a method cannot be found on it but is present on `T`.) - rust-lang#102338 (Deny associated type bindings within associated type bindings) - rust-lang#102347 (Unescaping cleanups) - rust-lang#102348 (Tweak `FulfillProcessor`.) - rust-lang#102378 (Use already resolved `self_ty` in `confirm_fn_pointer_candidate`) - rust-lang#102380 (rustdoc: remove redundant mobile `.source > .sidebar` CSS) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
2 parents d6734be + ce15514 commit 837bf37

File tree

54 files changed

+622
-127
lines changed

Some content is hidden

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

54 files changed

+622
-127
lines changed

compiler/rustc_codegen_cranelift/example/std_example.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)]
1+
#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
22

33
#[cfg(target_arch = "x86_64")]
44
use std::arch::x86_64::*;

compiler/rustc_codegen_gcc/tests/run/int.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Run-time:
44
// status: 0
55

6-
#![feature(bench_black_box, const_black_box, core_intrinsics, start)]
6+
#![feature(const_black_box, core_intrinsics, start)]
77

88
#![no_std]
99

compiler/rustc_error_codes/src/error_codes.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,7 @@ E0307: include_str!("./error_codes/E0307.md"),
159159
E0308: include_str!("./error_codes/E0308.md"),
160160
E0309: include_str!("./error_codes/E0309.md"),
161161
E0310: include_str!("./error_codes/E0310.md"),
162+
E0311: include_str!("./error_codes/E0311.md"),
162163
E0312: include_str!("./error_codes/E0312.md"),
163164
E0316: include_str!("./error_codes/E0316.md"),
164165
E0317: include_str!("./error_codes/E0317.md"),
@@ -568,7 +569,6 @@ E0790: include_str!("./error_codes/E0790.md"),
568569
// E0300, // unexpanded macro
569570
// E0304, // expected signed integer constant
570571
// E0305, // expected constant
571-
E0311, // thing may not live long enough
572572
E0313, // lifetime of borrowed pointer outlives lifetime of captured
573573
// variable
574574
// E0314, // closure outlives stack frame
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
This error occurs when there is an unsatisfied outlives bound involving an
2+
elided region and a generic type parameter or associated type.
3+
4+
Erroneous code example:
5+
6+
```compile_fail,E0311
7+
fn no_restriction<T>(x: &()) -> &() {
8+
with_restriction::<T>(x)
9+
}
10+
11+
fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
12+
x
13+
}
14+
```
15+
16+
Why doesn't this code compile? It helps to look at the lifetime bounds that are
17+
automatically added by the compiler. For more details see the documentation for
18+
[lifetime elision]( https://doc.rust-lang.org/reference/lifetime-elision.html).
19+
20+
The compiler elides the lifetime of `x` and the return type to some arbitrary
21+
lifetime `'anon` in `no_restriction()`. The only information available to the
22+
compiler is that `'anon` is valid for the duration of the function. When
23+
calling `with_restriction()`, the compiler requires the completely unrelated
24+
type parameter `T` to outlive `'anon` because of the `T: 'a` bound in
25+
`with_restriction()`. This causes an error because `T` is not required to
26+
outlive `'anon` in `no_restriction()`.
27+
28+
If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
29+
compiler would have added an implied bound, causing this to compile.
30+
31+
This error can be resolved by explicitly naming the elided lifetime for `x` and
32+
then explicily requiring that the generic parameter `T` outlives that lifetime:
33+
34+
```
35+
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
36+
with_restriction::<T>(x)
37+
}
38+
39+
fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
40+
x
41+
}
42+
```

compiler/rustc_hir_analysis/src/astconv/mod.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -595,16 +595,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
595595
"create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
596596
span, item_def_id, item_segment
597597
);
598-
self.create_substs_for_ast_path(
598+
let (args, _) = self.create_substs_for_ast_path(
599599
span,
600600
item_def_id,
601601
parent_substs,
602602
item_segment,
603603
item_segment.args(),
604604
item_segment.infer_args,
605605
None,
606-
)
607-
.0
606+
);
607+
608+
let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args());
609+
if let Some(b) = assoc_bindings.first() {
610+
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
611+
}
612+
613+
args
608614
}
609615

610616
/// Instantiates the path for the given trait reference, assuming that it's

compiler/rustc_hir_analysis/src/check/method/suggest.rs

+149-61
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//! found or is otherwise invalid.
33
44
use crate::check::FnCtxt;
5+
use rustc_ast::ast::Mutability;
56
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
67
use rustc_errors::{
78
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
@@ -30,7 +31,7 @@ use rustc_trait_selection::traits::{
3031
use std::cmp::Ordering;
3132
use std::iter;
3233

33-
use super::probe::{IsSuggestion, Mode, ProbeScope};
34+
use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
3435
use super::{CandidateSource, MethodError, NoMatchData};
3536

3637
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -983,7 +984,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
983984
self.check_for_field_method(&mut err, source, span, actual, item_name);
984985
}
985986

986-
self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
987+
self.check_for_inner_self(&mut err, source, span, actual, item_name);
987988

988989
bound_spans.sort();
989990
bound_spans.dedup();
@@ -1395,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13951396
}
13961397
}
13971398

1398-
fn check_for_unwrap_self(
1399+
fn check_for_inner_self(
13991400
&self,
14001401
err: &mut Diagnostic,
14011402
source: SelfSource<'tcx>,
@@ -1408,81 +1409,168 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
14081409
let call_expr = tcx.hir().expect_expr(tcx.hir().get_parent_node(expr.hir_id));
14091410

14101411
let ty::Adt(kind, substs) = actual.kind() else { return; };
1411-
if !kind.is_enum() {
1412-
return;
1413-
}
1412+
match kind.adt_kind() {
1413+
ty::AdtKind::Enum => {
1414+
let matching_variants: Vec<_> = kind
1415+
.variants()
1416+
.iter()
1417+
.flat_map(|variant| {
1418+
let [field] = &variant.fields[..] else { return None; };
1419+
let field_ty = field.ty(tcx, substs);
1420+
1421+
// Skip `_`, since that'll just lead to ambiguity.
1422+
if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1423+
return None;
1424+
}
14141425

1415-
let matching_variants: Vec<_> = kind
1416-
.variants()
1417-
.iter()
1418-
.flat_map(|variant| {
1419-
let [field] = &variant.fields[..] else { return None; };
1420-
let field_ty = field.ty(tcx, substs);
1426+
self.lookup_probe(
1427+
span,
1428+
item_name,
1429+
field_ty,
1430+
call_expr,
1431+
ProbeScope::TraitsInScope,
1432+
)
1433+
.ok()
1434+
.map(|pick| (variant, field, pick))
1435+
})
1436+
.collect();
1437+
1438+
let ret_ty_matches = |diagnostic_item| {
1439+
if let Some(ret_ty) = self
1440+
.ret_coercion
1441+
.as_ref()
1442+
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1443+
&& let ty::Adt(kind, _) = ret_ty.kind()
1444+
&& tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1445+
{
1446+
true
1447+
} else {
1448+
false
1449+
}
1450+
};
14211451

1422-
// Skip `_`, since that'll just lead to ambiguity.
1423-
if self.resolve_vars_if_possible(field_ty).is_ty_var() {
1424-
return None;
1452+
match &matching_variants[..] {
1453+
[(_, field, pick)] => {
1454+
let self_ty = field.ty(tcx, substs);
1455+
err.span_note(
1456+
tcx.def_span(pick.item.def_id),
1457+
&format!("the method `{item_name}` exists on the type `{self_ty}`"),
1458+
);
1459+
let (article, kind, variant, question) =
1460+
if tcx.is_diagnostic_item(sym::Result, kind.did()) {
1461+
("a", "Result", "Err", ret_ty_matches(sym::Result))
1462+
} else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
1463+
("an", "Option", "None", ret_ty_matches(sym::Option))
1464+
} else {
1465+
return;
1466+
};
1467+
if question {
1468+
err.span_suggestion_verbose(
1469+
expr.span.shrink_to_hi(),
1470+
format!(
1471+
"use the `?` operator to extract the `{self_ty}` value, propagating \
1472+
{article} `{kind}::{variant}` value to the caller"
1473+
),
1474+
"?",
1475+
Applicability::MachineApplicable,
1476+
);
1477+
} else {
1478+
err.span_suggestion_verbose(
1479+
expr.span.shrink_to_hi(),
1480+
format!(
1481+
"consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1482+
panicking if the value is {article} `{kind}::{variant}`"
1483+
),
1484+
".expect(\"REASON\")",
1485+
Applicability::HasPlaceholders,
1486+
);
1487+
}
1488+
}
1489+
// FIXME(compiler-errors): Support suggestions for other matching enum variants
1490+
_ => {}
14251491
}
1426-
1427-
self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
1428-
.ok()
1429-
.map(|pick| (variant, field, pick))
1430-
})
1431-
.collect();
1432-
1433-
let ret_ty_matches = |diagnostic_item| {
1434-
if let Some(ret_ty) = self
1435-
.ret_coercion
1436-
.as_ref()
1437-
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
1438-
&& let ty::Adt(kind, _) = ret_ty.kind()
1439-
&& tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
1440-
{
1441-
true
1442-
} else {
1443-
false
14441492
}
1445-
};
1493+
// Target wrapper types - types that wrap or pretend to wrap another type,
1494+
// perhaps this inner type is meant to be called?
1495+
ty::AdtKind::Struct | ty::AdtKind::Union => {
1496+
let [first] = ***substs else { return; };
1497+
let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
1498+
let Ok(pick) = self.lookup_probe(
1499+
span,
1500+
item_name,
1501+
ty,
1502+
call_expr,
1503+
ProbeScope::TraitsInScope,
1504+
) else { return; };
14461505

1447-
match &matching_variants[..] {
1448-
[(_, field, pick)] => {
1449-
let self_ty = field.ty(tcx, substs);
1450-
err.span_note(
1451-
tcx.def_span(pick.item.def_id),
1452-
&format!("the method `{item_name}` exists on the type `{self_ty}`"),
1453-
);
1454-
let (article, kind, variant, question) =
1455-
if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
1456-
("a", "Result", "Err", ret_ty_matches(sym::Result))
1457-
} else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
1458-
("an", "Option", "None", ret_ty_matches(sym::Option))
1459-
} else {
1460-
return;
1506+
let name = self.ty_to_value_string(actual);
1507+
let inner_id = kind.did();
1508+
let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
1509+
pick.autoref_or_ptr_adjustment
1510+
{
1511+
Some(mutbl)
1512+
} else {
1513+
None
1514+
};
1515+
1516+
if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
1517+
err.help("use `with` or `try_with` to access thread local storage");
1518+
} else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
1519+
err.help(format!(
1520+
"if this `{name}` has been initialized, \
1521+
use one of the `assume_init` methods to access the inner value"
1522+
));
1523+
} else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
1524+
let (suggestion, borrow_kind, panic_if) = match mutable {
1525+
Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
1526+
Some(Mutability::Mut) => {
1527+
(".borrow_mut()", "mutably borrow", "any borrows exist")
1528+
}
1529+
None => return,
14611530
};
1462-
if question {
14631531
err.span_suggestion_verbose(
14641532
expr.span.shrink_to_hi(),
14651533
format!(
1466-
"use the `?` operator to extract the `{self_ty}` value, propagating \
1467-
{article} `{kind}::{variant}` value to the caller"
1534+
"use `{suggestion}` to {borrow_kind} the `{ty}`, \
1535+
panicking if {panic_if}"
14681536
),
1469-
"?",
1470-
Applicability::MachineApplicable,
1537+
suggestion,
1538+
Applicability::MaybeIncorrect,
14711539
);
1472-
} else {
1540+
} else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
14731541
err.span_suggestion_verbose(
14741542
expr.span.shrink_to_hi(),
14751543
format!(
1476-
"consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
1477-
panicking if the value is {article} `{kind}::{variant}`"
1544+
"use `.lock().unwrap()` to borrow the `{ty}`, \
1545+
blocking the current thread until it can be acquired"
14781546
),
1479-
".expect(\"REASON\")",
1480-
Applicability::HasPlaceholders,
1547+
".lock().unwrap()",
1548+
Applicability::MaybeIncorrect,
14811549
);
1482-
}
1550+
} else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
1551+
let (suggestion, borrow_kind) = match mutable {
1552+
Some(Mutability::Not) => (".read().unwrap()", "borrow"),
1553+
Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
1554+
None => return,
1555+
};
1556+
err.span_suggestion_verbose(
1557+
expr.span.shrink_to_hi(),
1558+
format!(
1559+
"use `{suggestion}` to {borrow_kind} the `{ty}`, \
1560+
blocking the current thread until it can be acquired"
1561+
),
1562+
suggestion,
1563+
Applicability::MaybeIncorrect,
1564+
);
1565+
} else {
1566+
return;
1567+
};
1568+
1569+
err.span_note(
1570+
tcx.def_span(pick.item.def_id),
1571+
&format!("the method `{item_name}` exists on the type `{ty}`"),
1572+
);
14831573
}
1484-
// FIXME(compiler-errors): Support suggestions for other matching enum variants
1485-
_ => {}
14861574
}
14871575
}
14881576

compiler/rustc_index/src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![deny(rustc::untranslatable_diagnostic)]
22
#![deny(rustc::diagnostic_outside_of_impl)]
33
#![feature(allow_internal_unstable)]
4-
#![feature(bench_black_box)]
54
#![feature(extend_one)]
65
#![feature(min_specialization)]
76
#![feature(new_uninit)]

0 commit comments

Comments
 (0)