Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 8 pull requests #102388

Merged
merged 35 commits into from
Sep 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
fa91980
Add long description and test for E0311
MatthewPeterKelly Aug 19, 2022
08fa70e
fix updated stderr outputs
MatthewPeterKelly Aug 19, 2022
63de1ec
Apply suggestions from code review
MatthewPeterKelly Aug 19, 2022
a9cefd0
fix line lengths
MatthewPeterKelly Aug 19, 2022
dbcc409
Improve E0311.md description
MatthewPeterKelly Aug 23, 2022
231e3a0
actually fix typo this time
MatthewPeterKelly Aug 23, 2022
dd7c48e
Improve description again
MatthewPeterKelly Aug 25, 2022
fc02eee
fix wrapping
MatthewPeterKelly Aug 25, 2022
4f194a7
Fix rust-doc error
MatthewPeterKelly Aug 25, 2022
de3e95b
Review updates: simpler MWE and docs
MatthewPeterKelly Aug 26, 2022
deadf07
fix trailing `]`
MatthewPeterKelly Aug 27, 2022
4a443df
review updates to E0311 description
MatthewPeterKelly Aug 29, 2022
eda2a40
Merge remote-tracking branch 'origin/master' into mpk/add-long-error-…
MatthewPeterKelly Aug 31, 2022
24aab52
Merge remote-tracking branch 'origin/master' into mpk/add-long-error-…
MatthewPeterKelly Sep 26, 2022
0d9c014
remove implied link bound per review
MatthewPeterKelly Sep 27, 2022
c91c647
Fix an incorrect comment.
nnethercote Sep 27, 2022
b69c335
Tweak `FulfillProcessor`.
nnethercote Sep 27, 2022
9ad2f00
Stabilize bench_black_box
Urgau Sep 24, 2022
ca2e0bb
Deny associated type bindings within associated type bindings
compiler-errors Sep 27, 2022
c4c9415
Wrapper suggestions
Sep 25, 2022
f3ac328
Address feedback
Sep 27, 2022
e5776c6
Use already resolved self_ty in confirm_fn_pointer_candidate
compiler-errors Sep 27, 2022
e9224b3
Add newline
Sep 27, 2022
c0245b1
rustdoc: remove redundant mobile `.source > .sidebar` CSS
notriddle Sep 27, 2022
94cb5e8
Small cleanups in unescaping code.
nnethercote Sep 27, 2022
c0d32fd
review updates
MatthewPeterKelly Sep 27, 2022
4ff83ce
Deduplicate some logic
Sep 28, 2022
49bc668
Rollup merge of #100747 - MatthewPeterKelly:mpk/add-long-error-messag…
JohnTitor Sep 28, 2022
07bb2e6
Rollup merge of #102232 - Urgau:stabilize-bench_black_box, r=TaKO8Ki
JohnTitor Sep 28, 2022
9436ffc
Rollup merge of #102288 - mejrs:inner, r=compiler-errors
JohnTitor Sep 28, 2022
b263b7e
Rollup merge of #102338 - compiler-errors:assoc-ty-binding-in-assoc-t…
JohnTitor Sep 28, 2022
f0daff2
Rollup merge of #102347 - nnethercote:unescaping-cleanups, r=matklad
JohnTitor Sep 28, 2022
bf54cfe
Rollup merge of #102348 - nnethercote:tweak-FulfillProcessor, r=jackh726
JohnTitor Sep 28, 2022
ae20288
Rollup merge of #102378 - compiler-errors:issue-102289, r=jackh726
JohnTitor Sep 28, 2022
ce15514
Rollup merge of #102380 - notriddle:notriddle/rustdoc-source-sidebar,…
JohnTitor Sep 28, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/example/std_example.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(core_intrinsics, generators, generator_trait, is_sorted, bench_black_box)]
#![feature(core_intrinsics, generators, generator_trait, is_sorted)]

#[cfg(target_arch = "x86_64")]
use std::arch::x86_64::*;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_gcc/tests/run/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// Run-time:
// status: 0

#![feature(bench_black_box, const_black_box, core_intrinsics, start)]
#![feature(const_black_box, core_intrinsics, start)]

#![no_std]

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_error_codes/src/error_codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ E0307: include_str!("./error_codes/E0307.md"),
E0308: include_str!("./error_codes/E0308.md"),
E0309: include_str!("./error_codes/E0309.md"),
E0310: include_str!("./error_codes/E0310.md"),
E0311: include_str!("./error_codes/E0311.md"),
E0312: include_str!("./error_codes/E0312.md"),
E0316: include_str!("./error_codes/E0316.md"),
E0317: include_str!("./error_codes/E0317.md"),
Expand Down Expand Up @@ -568,7 +569,6 @@ E0790: include_str!("./error_codes/E0790.md"),
// E0300, // unexpanded macro
// E0304, // expected signed integer constant
// E0305, // expected constant
E0311, // thing may not live long enough
E0313, // lifetime of borrowed pointer outlives lifetime of captured
// variable
// E0314, // closure outlives stack frame
Expand Down
42 changes: 42 additions & 0 deletions compiler/rustc_error_codes/src/error_codes/E0311.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
This error occurs when there is an unsatisfied outlives bound involving an
elided region and a generic type parameter or associated type.

Erroneous code example:

```compile_fail,E0311
fn no_restriction<T>(x: &()) -> &() {
with_restriction::<T>(x)
}

fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
x
}
```

Why doesn't this code compile? It helps to look at the lifetime bounds that are
automatically added by the compiler. For more details see the documentation for
[lifetime elision]( https://doc.rust-lang.org/reference/lifetime-elision.html).

The compiler elides the lifetime of `x` and the return type to some arbitrary
lifetime `'anon` in `no_restriction()`. The only information available to the
compiler is that `'anon` is valid for the duration of the function. When
calling `with_restriction()`, the compiler requires the completely unrelated
type parameter `T` to outlive `'anon` because of the `T: 'a` bound in
`with_restriction()`. This causes an error because `T` is not required to
outlive `'anon` in `no_restriction()`.

If `no_restriction()` were to use `&T` instead of `&()` as an argument, the
compiler would have added an implied bound, causing this to compile.

This error can be resolved by explicitly naming the elided lifetime for `x` and
then explicily requiring that the generic parameter `T` outlives that lifetime:

```
fn no_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
with_restriction::<T>(x)
}

fn with_restriction<'a, T: 'a>(x: &'a ()) -> &'a () {
x
}
```
12 changes: 9 additions & 3 deletions compiler/rustc_hir_analysis/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -595,16 +595,22 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
"create_substs_for_associated_item(span: {:?}, item_def_id: {:?}, item_segment: {:?}",
span, item_def_id, item_segment
);
self.create_substs_for_ast_path(
let (args, _) = self.create_substs_for_ast_path(
span,
item_def_id,
parent_substs,
item_segment,
item_segment.args(),
item_segment.infer_args,
None,
)
.0
);

let assoc_bindings = self.create_assoc_bindings_for_generic_args(item_segment.args());
if let Some(b) = assoc_bindings.first() {
Self::prohibit_assoc_ty_binding(self.tcx(), b.span);
}

args
}

/// Instantiates the path for the given trait reference, assuming that it's
Expand Down
210 changes: 149 additions & 61 deletions compiler/rustc_hir_analysis/src/check/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
//! found or is otherwise invalid.

use crate::check::FnCtxt;
use rustc_ast::ast::Mutability;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::{
pluralize, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
Expand Down Expand Up @@ -30,7 +31,7 @@ use rustc_trait_selection::traits::{
use std::cmp::Ordering;
use std::iter;

use super::probe::{IsSuggestion, Mode, ProbeScope};
use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
use super::{CandidateSource, MethodError, NoMatchData};

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

self.check_for_unwrap_self(&mut err, source, span, actual, item_name);
self.check_for_inner_self(&mut err, source, span, actual, item_name);

bound_spans.sort();
bound_spans.dedup();
Expand Down Expand Up @@ -1395,7 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

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

let ty::Adt(kind, substs) = actual.kind() else { return; };
if !kind.is_enum() {
return;
}
match kind.adt_kind() {
ty::AdtKind::Enum => {
let matching_variants: Vec<_> = kind
.variants()
.iter()
.flat_map(|variant| {
let [field] = &variant.fields[..] else { return None; };
let field_ty = field.ty(tcx, substs);

// Skip `_`, since that'll just lead to ambiguity.
if self.resolve_vars_if_possible(field_ty).is_ty_var() {
return None;
}

let matching_variants: Vec<_> = kind
.variants()
.iter()
.flat_map(|variant| {
let [field] = &variant.fields[..] else { return None; };
let field_ty = field.ty(tcx, substs);
self.lookup_probe(
span,
item_name,
field_ty,
call_expr,
ProbeScope::TraitsInScope,
)
.ok()
.map(|pick| (variant, field, pick))
})
.collect();

let ret_ty_matches = |diagnostic_item| {
if let Some(ret_ty) = self
.ret_coercion
.as_ref()
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
&& let ty::Adt(kind, _) = ret_ty.kind()
&& tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
{
true
} else {
false
}
};

// Skip `_`, since that'll just lead to ambiguity.
if self.resolve_vars_if_possible(field_ty).is_ty_var() {
return None;
match &matching_variants[..] {
[(_, field, pick)] => {
let self_ty = field.ty(tcx, substs);
err.span_note(
tcx.def_span(pick.item.def_id),
&format!("the method `{item_name}` exists on the type `{self_ty}`"),
);
let (article, kind, variant, question) =
if tcx.is_diagnostic_item(sym::Result, kind.did()) {
("a", "Result", "Err", ret_ty_matches(sym::Result))
} else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
("an", "Option", "None", ret_ty_matches(sym::Option))
} else {
return;
};
if question {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
"use the `?` operator to extract the `{self_ty}` value, propagating \
{article} `{kind}::{variant}` value to the caller"
),
"?",
Applicability::MachineApplicable,
);
} else {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
"consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
panicking if the value is {article} `{kind}::{variant}`"
),
".expect(\"REASON\")",
Applicability::HasPlaceholders,
);
}
}
// FIXME(compiler-errors): Support suggestions for other matching enum variants
_ => {}
}

self.lookup_probe(span, item_name, field_ty, call_expr, ProbeScope::AllTraits)
.ok()
.map(|pick| (variant, field, pick))
})
.collect();

let ret_ty_matches = |diagnostic_item| {
if let Some(ret_ty) = self
.ret_coercion
.as_ref()
.map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
&& let ty::Adt(kind, _) = ret_ty.kind()
&& tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
{
true
} else {
false
}
};
// Target wrapper types - types that wrap or pretend to wrap another type,
// perhaps this inner type is meant to be called?
ty::AdtKind::Struct | ty::AdtKind::Union => {
let [first] = ***substs else { return; };
let ty::GenericArgKind::Type(ty) = first.unpack() else { return; };
let Ok(pick) = self.lookup_probe(
span,
item_name,
ty,
call_expr,
ProbeScope::TraitsInScope,
) else { return; };

match &matching_variants[..] {
[(_, field, pick)] => {
let self_ty = field.ty(tcx, substs);
err.span_note(
tcx.def_span(pick.item.def_id),
&format!("the method `{item_name}` exists on the type `{self_ty}`"),
);
let (article, kind, variant, question) =
if Some(kind.did()) == tcx.get_diagnostic_item(sym::Result) {
("a", "Result", "Err", ret_ty_matches(sym::Result))
} else if Some(kind.did()) == tcx.get_diagnostic_item(sym::Option) {
("an", "Option", "None", ret_ty_matches(sym::Option))
} else {
return;
let name = self.ty_to_value_string(actual);
let inner_id = kind.did();
let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
pick.autoref_or_ptr_adjustment
{
Some(mutbl)
} else {
None
};

if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
err.help("use `with` or `try_with` to access thread local storage");
} else if Some(kind.did()) == tcx.lang_items().maybe_uninit() {
err.help(format!(
"if this `{name}` has been initialized, \
use one of the `assume_init` methods to access the inner value"
));
} else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
let (suggestion, borrow_kind, panic_if) = match mutable {
Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
Some(Mutability::Mut) => {
(".borrow_mut()", "mutably borrow", "any borrows exist")
}
None => return,
};
if question {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
"use the `?` operator to extract the `{self_ty}` value, propagating \
{article} `{kind}::{variant}` value to the caller"
"use `{suggestion}` to {borrow_kind} the `{ty}`, \
panicking if {panic_if}"
),
"?",
Applicability::MachineApplicable,
suggestion,
Applicability::MaybeIncorrect,
);
} else {
} else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
"consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
panicking if the value is {article} `{kind}::{variant}`"
"use `.lock().unwrap()` to borrow the `{ty}`, \
blocking the current thread until it can be acquired"
),
".expect(\"REASON\")",
Applicability::HasPlaceholders,
".lock().unwrap()",
Applicability::MaybeIncorrect,
);
}
} else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
let (suggestion, borrow_kind) = match mutable {
Some(Mutability::Not) => (".read().unwrap()", "borrow"),
Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
None => return,
};
err.span_suggestion_verbose(
expr.span.shrink_to_hi(),
format!(
"use `{suggestion}` to {borrow_kind} the `{ty}`, \
blocking the current thread until it can be acquired"
),
suggestion,
Applicability::MaybeIncorrect,
);
} else {
return;
};

err.span_note(
tcx.def_span(pick.item.def_id),
&format!("the method `{item_name}` exists on the type `{ty}`"),
);
}
// FIXME(compiler-errors): Support suggestions for other matching enum variants
_ => {}
}
}

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_index/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(allow_internal_unstable)]
#![feature(bench_black_box)]
#![feature(extend_one)]
#![feature(min_specialization)]
#![feature(new_uninit)]
Expand Down
Loading