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 6 pull requests #116453

Closed
wants to merge 21 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
702da3b
stabilize `Option::as_`(`mut_`)`slice`
llogiq Sep 28, 2023
9130484
create localdecl and add span to it
ouz-a Sep 30, 2023
999a354
add span to terminator
ouz-a Sep 30, 2023
2817ece
Show more information when multiple `impl` apply
estebank Aug 14, 2023
91b9ffe
Reorder fullfillment errors to keep more interesting ones first
estebank Aug 14, 2023
7313c10
Show suggestion for `<SelfTy as Trait>::assoc_fn` in more cases and f…
estebank Aug 14, 2023
4a0c676
Update docs for E0282 and E0283, as E0282 now doesn't trigger for `co…
estebank Aug 14, 2023
fd3804a
Split `traits::error_reporting` to keep files smaller
estebank Sep 28, 2023
8d92c99
Fix test on WASM target by making ambiguity pruning more agressive
estebank Oct 4, 2023
5453a9f
Add a note to duplicate diagnostics
Alexendoo Oct 4, 2023
a79567b
add span to statements
ouz-a Sep 30, 2023
a49138e
impl stable for kinds
ouz-a Oct 5, 2023
14c846c
Do not assert that hidden types don't have erased regions.
cjgillot Oct 5, 2023
5529a34
Fix windows test that has different stderr output
estebank Oct 5, 2023
3088c4b
move subtyper change reveal_all
ouz-a Oct 3, 2023
44e37ea
Rollup merge of #114811 - estebank:impl-ambiguity, r=wesleywiser
matthiaskrgr Oct 5, 2023
50de0e6
Rollup merge of #116220 - llogiq:stabilize-option-as-slice, r=BurntSushi
matthiaskrgr Oct 5, 2023
f27068c
Rollup merge of #116288 - ouz-a:smir_spans, r=spastorino
matthiaskrgr Oct 5, 2023
9fe16a4
Rollup merge of #116415 - ouz-a:move_subtyper, r=oli-obk
matthiaskrgr Oct 5, 2023
91f486a
Rollup merge of #116428 - Alexendoo:note-duplicate-diagnostics, r=com…
matthiaskrgr Oct 5, 2023
656eff3
Rollup merge of #116452 - cjgillot:noassert-erased, r=oli-obk
matthiaskrgr Oct 5, 2023
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_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ fn check_opaque_type_well_formed<'tcx>(
if errors.is_empty() {
Ok(definition_ty)
} else {
Err(infcx.err_ctxt().report_fulfillment_errors(&errors))
Err(infcx.err_ctxt().report_fulfillment_errors(errors))
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -743,7 +743,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {

let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
}

// Attempting to call a trait method?
Expand Down
25 changes: 14 additions & 11 deletions compiler/rustc_error_codes/src/error_codes/E0282.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,29 +3,32 @@ The compiler could not infer a type and asked for a type annotation.
Erroneous code example:

```compile_fail,E0282
let x = "hello".chars().rev().collect();
let x = Vec::new();
```

This error indicates that type inference did not result in one unique possible
type, and extra information is required. In most cases this can be provided
by adding a type annotation. Sometimes you need to specify a generic type
parameter manually.

A common example is the `collect` method on `Iterator`. It has a generic type
parameter with a `FromIterator` bound, which for a `char` iterator is
implemented by `Vec` and `String` among others. Consider the following snippet
that reverses the characters of a string:
In the example above, type `Vec` has a type parameter `T`. When calling
`Vec::new`, barring any other later usage of the variable `x` that allows the
compiler to infer what type `T` is, the compiler needs to be told what it is.

In the first code example, the compiler cannot infer what the type of `x` should
be: `Vec<char>` and `String` are both suitable candidates. To specify which type
to use, you can use a type annotation on `x`:
The type can be specified on the variable:

```
let x: Vec<char> = "hello".chars().rev().collect();
let x: Vec<i32> = Vec::new();
```

It is not necessary to annotate the full type. Once the ambiguity is resolved,
the compiler can infer the rest:
The type can also be specified in the path of the expression:

```
let x = Vec::<i32>::new();
```

In cases with more complex types, it is not necessary to annotate the full
type. Once the ambiguity is resolved, the compiler can infer the rest:

```
let x: Vec<_> = "hello".chars().rev().collect();
Expand Down
46 changes: 45 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0283.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,51 @@
An implementation cannot be chosen unambiguously because of lack of information.
The compiler could not infer a type and asked for a type annotation.

Erroneous code example:

```compile_fail,E0283
let x = "hello".chars().rev().collect();
```

This error indicates that type inference did not result in one unique possible
type, and extra information is required. In most cases this can be provided
by adding a type annotation. Sometimes you need to specify a generic type
parameter manually.

A common example is the `collect` method on `Iterator`. It has a generic type
parameter with a `FromIterator` bound, which for a `char` iterator is
implemented by `Vec` and `String` among others. Consider the following snippet
that reverses the characters of a string:

In the first code example, the compiler cannot infer what the type of `x` should
be: `Vec<char>` and `String` are both suitable candidates. To specify which type
to use, you can use a type annotation on `x`:

```
let x: Vec<char> = "hello".chars().rev().collect();
```

It is not necessary to annotate the full type. Once the ambiguity is resolved,
the compiler can infer the rest:

```
let x: Vec<_> = "hello".chars().rev().collect();
```

Another way to provide the compiler with enough information, is to specify the
generic type parameter:

```
let x = "hello".chars().rev().collect::<Vec<char>>();
```

Again, you need not specify the full type if the compiler can infer it:

```
let x = "hello".chars().rev().collect::<Vec<_>>();
```

We can see a self-contained example below:

```compile_fail,E0283
struct Foo;

Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1376,16 +1376,16 @@ impl HandlerInner {
self.emitted_diagnostic_codes.insert(code.clone());
}

let already_emitted = |this: &mut Self| {
let already_emitted = {
let mut hasher = StableHasher::new();
diagnostic.hash(&mut hasher);
let diagnostic_hash = hasher.finish();
!this.emitted_diagnostics.insert(diagnostic_hash)
!self.emitted_diagnostics.insert(diagnostic_hash)
};

// Only emit the diagnostic if we've been asked to deduplicate or
// haven't already emitted an equivalent diagnostic.
if !(self.flags.deduplicate_diagnostics && already_emitted(self)) {
if !(self.flags.deduplicate_diagnostics && already_emitted) {
debug!(?diagnostic);
debug!(?self.emitted_diagnostics);
let already_emitted_sub = |sub: &mut SubDiagnostic| {
Expand All @@ -1401,6 +1401,11 @@ impl HandlerInner {
};

diagnostic.children.extract_if(already_emitted_sub).for_each(|_| {});
if already_emitted {
diagnostic.note(
"duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`",
);
}

self.emitter.emit_diagnostic(diagnostic);
if diagnostic.is_error() {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ fn check_opaque_meets_bounds<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
let guar = infcx.err_ctxt().report_fulfillment_errors(&errors);
let guar = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(guar);
}
match origin {
Expand Down Expand Up @@ -1512,6 +1512,6 @@ pub(super) fn check_generator_obligations(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let errors = fulfillment_cx.select_all_or_error(&infcx);
debug!(?errors);
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
}
}
12 changes: 6 additions & 6 deletions compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ fn compare_method_predicate_entailment<'tcx>(
// FIXME(-Ztrait-solver=next): Not needed when the hack below is removed.
let errors = ocx.select_where_possible();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);
}

Expand Down Expand Up @@ -394,7 +394,7 @@ fn compare_method_predicate_entailment<'tcx>(
});
}
CheckImpliedWfMode::Skip => {
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);
}
}
Expand Down Expand Up @@ -874,7 +874,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
// RPITs.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);
}

Expand Down Expand Up @@ -2050,7 +2050,7 @@ fn compare_const_predicate_entailment<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
return Err(infcx.err_ctxt().report_fulfillment_errors(&errors));
return Err(infcx.err_ctxt().report_fulfillment_errors(errors));
}

let outlives_env = OutlivesEnvironment::new(param_env);
Expand Down Expand Up @@ -2143,7 +2143,7 @@ fn compare_type_predicate_entailment<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);
}

Expand Down Expand Up @@ -2358,7 +2358,7 @@ pub(super) fn check_type_bounds<'tcx>(
// version.
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
let reported = infcx.err_ctxt().report_fulfillment_errors(&errors);
let reported = infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(reported);
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ fn check_main_fn_ty(tcx: TyCtxt<'_>, main_def_id: DefId) {
ocx.register_bound(cause, param_env, norm_return_ty, term_did);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
error = true;
}
// now we can take the return type of the given main function
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -588,7 +588,7 @@ pub fn check_function_signature<'tcx>(
Ok(()) => {
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(

let errors = wfcx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
return;
}

Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_hir_analysis/src/coherence/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef
}
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
}

// Finally, resolve all regions.
Expand Down Expand Up @@ -470,7 +470,7 @@ pub fn coerce_unsized_info<'tcx>(tcx: TyCtxt<'tcx>, impl_did: LocalDefId) -> Coe
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
}

// Finally, resolve all regions.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ fn get_impl_args(

let errors = ocx.select_all_or_error();
if !errors.is_empty() {
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(&errors);
let guar = ocx.infcx.err_ctxt().report_fulfillment_errors(errors);
return Err(guar);
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2958,7 +2958,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// There should be at least one error reported. If not, we
// will still delay a span bug in `report_fulfillment_errors`.
Ok::<_, NoSolution>((
self.err_ctxt().report_fulfillment_errors(&errors),
self.err_ctxt().report_fulfillment_errors(errors),
impl_trait_ref.args.type_at(1),
element_ty,
))
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {

if !errors.is_empty() {
self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
self.err_ctxt().report_fulfillment_errors(&errors);
self.err_ctxt().report_fulfillment_errors(errors);
}
}

Expand All @@ -577,7 +577,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if !result.is_empty() {
mutate_fulfillment_errors(&mut result);
self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
self.err_ctxt().report_fulfillment_errors(&result);
self.err_ctxt().report_fulfillment_errors(result);
}
}

Expand Down Expand Up @@ -1477,7 +1477,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
Ok(normalized_ty) => normalized_ty,
Err(errors) => {
let guar = self.err_ctxt().report_fulfillment_errors(&errors);
let guar = self.err_ctxt().report_fulfillment_errors(errors);
return Ty::new_error(self.tcx,guar);
}
}
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_typeck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#![feature(box_patterns)]
#![feature(min_specialization)]
#![feature(control_flow_enum)]
#![feature(option_as_slice)]
#![recursion_limit = "256"]

#[macro_use]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use std::iter;

pub enum TypeAnnotationNeeded {
/// ```compile_fail,E0282
/// let x = "hello".chars().rev().collect();
/// let x;
/// ```
E0282,
/// An implementation cannot be chosen unambiguously because of lack of information.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
rvalue: &mut Rvalue<'tcx>,
location: Location,
) {
// We don't need to do anything for deref temps as they are
// not part of the source code, but used for desugaring purposes.
if self.local_decls[place.local].is_deref_temp() {
return;
}
let mut place_ty = place.ty(self.local_decls, self.tcx).ty;
let mut rval_ty = rvalue.ty(self.local_decls, self.tcx);
// Not erasing this causes `Free Regions` errors in validator,
Expand All @@ -48,7 +53,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
// // gets transformed to
// let temp: rval_ty = rval;
// let place: place_ty = temp as place_ty;
//
pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let patch = MirPatch::new(body);
let mut checker = SubTypeChecker { tcx, patcher: patch, local_decls: &body.local_decls };
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_transform/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -467,7 +467,6 @@ pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'
/// After this series of passes, no lifetime analysis based on borrowing can be done.
fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let passes: &[&dyn MirPass<'tcx>] = &[
&add_subtyping_projections::Subtyper,
&cleanup_post_borrowck::CleanupPostBorrowck,
&remove_noop_landing_pads::RemoveNoopLandingPads,
&simplify::SimplifyCfg::EarlyOpt,
Expand All @@ -483,6 +482,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// These next passes must be executed together
&add_call_guards::CriticalCallEdges,
&reveal_all::RevealAll, // has to be done before drop elaboration, since we need to drop opaque types, too.
&add_subtyping_projections::Subtyper, // calling this after reveal_all ensures that we don't deal with opaque types
&elaborate_drops::ElaborateDrops,
// This will remove extraneous landing pads which are no longer
// necessary as well as well as forcing any call in a non-unwinding
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_mir_transform/src/reveal_all.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ impl<'tcx> MutVisitor<'tcx> for RevealAllVisitor<'tcx> {
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(_)))
.collect::<Vec<_>>(),
);
self.super_place(place, _context, _location);
}

#[inline]
fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, _: Location) {
fn visit_constant(&mut self, constant: &mut ConstOperand<'tcx>, location: Location) {
// We have to use `try_normalize_erasing_regions` here, since it's
// possible that we visit impossible-to-satisfy where clauses here,
// see #91745
if let Ok(c) = self.tcx.try_normalize_erasing_regions(self.param_env, constant.const_) {
constant.const_ = c;
}
self.super_constant(constant, location);
}

#[inline]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2373,7 +2373,7 @@ impl CheckAttrVisitor<'_> {

let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
self.abort.set(true);
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_passes/src/layout_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub fn ensure_wf<'tcx>(
ocx.register_obligation(obligation);
let errors = ocx.select_all_or_error();
if !errors.is_empty() {
infcx.err_ctxt().report_fulfillment_errors(&errors);
infcx.err_ctxt().report_fulfillment_errors(errors);
false
} else {
// looks WF!
Expand Down
Loading