diff options
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_typeck/src/check/wfcheck.rs | 40 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/lib.rs | 1 |
2 files changed, 31 insertions, 10 deletions
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index dc9784594c2..0ab9855d325 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -288,7 +288,6 @@ fn check_gat_where_clauses( associated_items.in_definition_order().filter(|item| matches!(item.kind, ty::AssocKind::Fn)) { let id = hir::HirId::make_owner(item.def_id.expect_local()); - let span = DUMMY_SP; let param_env = tcx.param_env(item.def_id.expect_local()); let sig = tcx.fn_sig(item.def_id); @@ -308,7 +307,7 @@ fn check_gat_where_clauses( for (ty, ty_idx) in &visitor.types { tcx.infer_ctxt().enter(|infcx| { let mut outlives_environment = OutlivesEnvironment::new(param_env); - outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, span); + outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id, DUMMY_SP); outlives_environment.save_implied_bounds(id); let region_bound_pairs = outlives_environment.region_bound_pairs_map().get(&id).unwrap(); @@ -349,7 +348,6 @@ fn check_gat_where_clauses( name: ty_param.name, })); let region_param = generics.param_at(*region_idx, tcx); - // Then create a clause that is required on the GAT let region_param = tcx.mk_region(ty::RegionKind::ReEarlyBound(ty::EarlyBoundRegion { def_id: region_param.def_id, @@ -372,13 +370,35 @@ fn check_gat_where_clauses( debug!(?clauses); if !clauses.is_empty() { let written_predicates: ty::GenericPredicates<'_> = tcx.predicates_of(trait_item.def_id); - for clause in clauses { - let found = written_predicates.predicates.iter().find(|p| p.0 == clause).is_some(); - debug!(?clause, ?found); - let mut error = tcx - .sess - .struct_span_err(trait_item.generics.span, &format!("Missing bound: {}", clause)); - error.emit(); + let clauses: Vec<_> = clauses + .drain_filter(|clause| { + written_predicates.predicates.iter().find(|p| &p.0 == clause).is_none() + }) + .map(|clause| format!("{}", clause)) + .collect(); + if !clauses.is_empty() { + let mut err = tcx.sess.struct_span_err( + trait_item.span, + &format!("Missing required bounds on {}", trait_item.ident), + ); + + let suggestion = format!( + "{} {}", + if !trait_item.generics.where_clause.predicates.is_empty() { + "," + } else { + " where" + }, + clauses.join(", "), + ); + err.span_suggestion( + trait_item.generics.where_clause.tail_span_for_suggestion(), + "add the required where clauses", + suggestion, + Applicability::MachineApplicable, + ); + + err.emit() } } } diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs index 971776c882a..50afdc23631 100644 --- a/compiler/rustc_typeck/src/lib.rs +++ b/compiler/rustc_typeck/src/lib.rs @@ -69,6 +69,7 @@ This API is completely unstable and subject to change. #![feature(never_type)] #![feature(slice_partition_dedup)] #![feature(control_flow_enum)] +#![feature(hash_drain_filter)] #![recursion_limit = "256"] #[macro_use] |
