Skip to content

Commit a395214

Browse files
committedOct 30, 2023
Auto merge of #116405 - estebank:issue-103155, r=davidtwco
Detect object safety errors when assoc type is missing When an associated type with GATs isn't specified in a `dyn Trait`, emit an object safety error instead of only complaining about the missing associated type, as it will lead the user down a path of three different errors before letting them know that what they were trying to do is impossible to begin with. Fix #103155.
2 parents 31bc7e2 + b8a8ba9 commit a395214

38 files changed

+249
-193
lines changed
 

‎compiler/rustc_hir_analysis/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ hir_analysis_unused_associated_type_bounds =
404404
.suggestion = remove this bound
405405
406406
hir_analysis_value_of_associated_struct_already_specified =
407-
the value of the associated type `{$item_name}` (from trait `{$def_path}`) is already specified
407+
the value of the associated type `{$item_name}` in trait `{$def_path}` is already specified
408408
.label = re-bound here
409409
.previous_bound_label = `{$item_name}` bound here first
410410

‎compiler/rustc_hir_analysis/src/astconv/errors.rs

+39-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::errors::{
33
AssocTypeBindingNotAllowed, ManualImplementation, MissingTypeParams,
44
ParenthesizedFnTraitExpansion,
55
};
6+
use crate::traits::error_reporting::report_object_safety_error;
67
use rustc_data_structures::fx::FxHashMap;
78
use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed};
89
use rustc_hir as hir;
@@ -13,6 +14,7 @@ use rustc_session::parse::feature_err;
1314
use rustc_span::edit_distance::find_best_match_for_name;
1415
use rustc_span::symbol::{sym, Ident};
1516
use rustc_span::{Span, Symbol, DUMMY_SP};
17+
use rustc_trait_selection::traits::object_safety_violations_for_assoc_item;
1618

1719
use std::collections::BTreeSet;
1820

@@ -520,24 +522,33 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
520522
(span, def_ids.into_iter().map(|did| tcx.associated_item(did)).collect())
521523
})
522524
.collect();
523-
let mut names = vec![];
525+
let mut names: FxHashMap<String, Vec<Symbol>> = Default::default();
526+
let mut names_len = 0;
524527

525528
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
526529
// `issue-22560.rs`.
527530
let mut trait_bound_spans: Vec<Span> = vec![];
531+
let mut object_safety_violations = false;
528532
for (span, items) in &associated_types {
529533
if !items.is_empty() {
530534
trait_bound_spans.push(*span);
531535
}
532536
for assoc_item in items {
533537
let trait_def_id = assoc_item.container_id(tcx);
534-
names.push(format!(
535-
"`{}` (from trait `{}`)",
536-
assoc_item.name,
537-
tcx.def_path_str(trait_def_id),
538-
));
538+
names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name);
539+
names_len += 1;
540+
541+
let violations =
542+
object_safety_violations_for_assoc_item(tcx, trait_def_id, *assoc_item);
543+
if !violations.is_empty() {
544+
report_object_safety_error(tcx, *span, trait_def_id, &violations).emit();
545+
object_safety_violations = true;
546+
}
539547
}
540548
}
549+
if object_safety_violations {
550+
return;
551+
}
541552
if let ([], [bound]) = (&potential_assoc_types[..], &trait_bounds) {
542553
match bound.trait_ref.path.segments {
543554
// FIXME: `trait_ref.path.span` can point to a full path with multiple
@@ -573,15 +584,35 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
573584
_ => {}
574585
}
575586
}
587+
588+
let mut names = names
589+
.into_iter()
590+
.map(|(trait_, mut assocs)| {
591+
assocs.sort();
592+
format!(
593+
"{} in `{trait_}`",
594+
match &assocs[..] {
595+
[] => String::new(),
596+
[only] => format!("`{only}`"),
597+
[assocs @ .., last] => format!(
598+
"{} and `{last}`",
599+
assocs.iter().map(|a| format!("`{a}`")).collect::<Vec<_>>().join(", ")
600+
),
601+
}
602+
)
603+
})
604+
.collect::<Vec<String>>();
576605
names.sort();
606+
let names = names.join(", ");
607+
577608
trait_bound_spans.sort();
578609
let mut err = struct_span_err!(
579610
tcx.sess,
580611
trait_bound_spans,
581612
E0191,
582613
"the value of the associated type{} {} must be specified",
583-
pluralize!(names.len()),
584-
names.join(", "),
614+
pluralize!(names_len),
615+
names,
585616
);
586617
let mut suggestions = vec![];
587618
let mut types_count = 0;

‎compiler/rustc_hir_analysis/src/astconv/object_safety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
380380
span,
381381
E0228,
382382
"the lifetime bound for this object type cannot be deduced \
383-
from context; please supply an explicit bound"
383+
from context; please supply an explicit bound"
384384
);
385385
let e = if borrowed {
386386
// We will have already emitted an error E0106 complaining about a

‎compiler/rustc_trait_selection/src/traits/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub use self::engine::{ObligationCtxt, TraitEngineExt};
4747
pub use self::fulfill::{FulfillmentContext, PendingPredicateObligation};
4848
pub use self::object_safety::astconv_object_safety_violations;
4949
pub use self::object_safety::is_vtable_safe_method;
50-
pub use self::object_safety::MethodViolationCode;
50+
pub use self::object_safety::object_safety_violations_for_assoc_item;
5151
pub use self::object_safety::ObjectSafetyViolation;
5252
pub use self::project::NormalizeExt;
5353
pub use self::project::{normalize_inherent_projection, normalize_projection_type};

‎compiler/rustc_trait_selection/src/traits/object_safety.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
360360

361361
/// Returns `Some(_)` if this item makes the containing trait not object safe.
362362
#[instrument(level = "debug", skip(tcx), ret)]
363-
fn object_safety_violations_for_assoc_item(
363+
pub fn object_safety_violations_for_assoc_item(
364364
tcx: TyCtxt<'_>,
365365
trait_def_id: DefId,
366366
item: ty::AssocItem,

0 commit comments

Comments
 (0)
Please sign in to comment.