diff options
| author | Michael Goulet <michael@errs.io> | 2024-11-23 18:46:50 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-12-11 19:53:40 +0000 |
| commit | 43e2fd5086debfa74f33f6c323d21a756abb8236 (patch) | |
| tree | d4e6bb82a71eff8e9be65435ea465cd957735ee2 /compiler/rustc_hir_analysis/src | |
| parent | 25a7fdf5bc68758fb1a12e2f5ee7fbce0e6a70bb (diff) | |
| download | rust-43e2fd5086debfa74f33f6c323d21a756abb8236.tar.gz rust-43e2fd5086debfa74f33f6c323d21a756abb8236.zip | |
Fix ICE when multiple supertrait substitutions need assoc but only one is provided
Diffstat (limited to 'compiler/rustc_hir_analysis/src')
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs | 13 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs | 42 |
2 files changed, 32 insertions, 23 deletions
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 6e5f2415057..71a5727ed6c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -145,16 +145,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let bound_predicate = pred.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { - let pred = bound_predicate.rebind(pred); + // FIXME(negative_bounds): Handle this correctly... + let trait_ref = + tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref)); needed_associated_types.extend( - tcx.associated_items(pred.def_id()) + tcx.associated_items(trait_ref.def_id()) .in_definition_order() .filter(|item| item.kind == ty::AssocKind::Type) .filter(|item| !item.is_impl_trait_in_trait()) // If the associated type has a `where Self: Sized` bound, // we do not need to constrain the associated type. .filter(|item| !tcx.generics_require_sized_self(item.def_id)) - .map(|item| item.def_id), + .map(|item| (item.def_id, trait_ref)), ); } ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => { @@ -206,7 +208,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // corresponding `Projection` clause for (projection_bound, span) in &projection_bounds { let def_id = projection_bound.item_def_id(); - needed_associated_types.swap_remove(&def_id); + let trait_ref = tcx.anonymize_bound_vars( + projection_bound.map_bound(|p| p.projection_term.trait_ref(tcx)), + ); + needed_associated_types.swap_remove(&(def_id, trait_ref)); if tcx.generics_require_sized_self(def_id) { tcx.emit_node_span_lint( UNUSED_ASSOCIATED_TYPE_BOUNDS, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 3c40d33e8ca..a66b0b32238 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -723,7 +723,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { pub(crate) fn check_for_required_assoc_tys( &self, principal_span: Span, - missing_assoc_types: FxIndexSet<DefId>, + missing_assoc_types: FxIndexSet<(DefId, ty::PolyTraitRef<'tcx>)>, potential_assoc_types: Vec<usize>, trait_bounds: &[hir::PolyTraitRef<'_>], ) -> Result<(), ErrorGuaranteed> { @@ -732,27 +732,29 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } let tcx = self.tcx(); - let missing_assoc_types: Vec<_> = - missing_assoc_types.into_iter().map(|def_id| tcx.associated_item(def_id)).collect(); - let mut names: FxIndexMap<String, Vec<Symbol>> = Default::default(); + // FIXME: This logic needs some more care w.r.t handling of conflicts + let missing_assoc_types: Vec<_> = missing_assoc_types + .into_iter() + .map(|(def_id, trait_ref)| (tcx.associated_item(def_id), trait_ref)) + .collect(); + let mut names: FxIndexMap<_, Vec<Symbol>> = Default::default(); let mut names_len = 0; // Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and // `issue-22560.rs`. let mut dyn_compatibility_violations = Ok(()); - for assoc_item in &missing_assoc_types { - let trait_def_id = assoc_item.container_id(tcx); - names.entry(tcx.def_path_str(trait_def_id)).or_default().push(assoc_item.name); + for (assoc_item, trait_ref) in &missing_assoc_types { + names.entry(trait_ref).or_default().push(assoc_item.name); names_len += 1; let violations = - dyn_compatibility_violations_for_assoc_item(tcx, trait_def_id, *assoc_item); + dyn_compatibility_violations_for_assoc_item(tcx, trait_ref.def_id(), *assoc_item); if !violations.is_empty() { dyn_compatibility_violations = Err(report_dyn_incompatibility( tcx, principal_span, None, - trait_def_id, + trait_ref.def_id(), &violations, ) .emit()); @@ -803,6 +805,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .into_iter() .map(|(trait_, mut assocs)| { assocs.sort(); + let trait_ = trait_.print_trait_sugared(); format!("{} in `{trait_}`", match &assocs[..] { [] => String::new(), [only] => format!("`{only}`"), @@ -830,19 +833,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let mut already_has_generics_args_suggestion = false; let mut names: UnordMap<_, usize> = Default::default(); - for item in &missing_assoc_types { + for (item, _) in &missing_assoc_types { types_count += 1; *names.entry(item.name).or_insert(0) += 1; } let mut dupes = false; let mut shadows = false; - for item in &missing_assoc_types { + for (item, trait_ref) in &missing_assoc_types { let prefix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); + let trait_def_id = trait_ref.def_id(); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) } else if bound_names.get(&item.name).is_some_and(|x| *x != item) { - let trait_def_id = item.container_id(tcx); + let trait_def_id = trait_ref.def_id(); shadows = true; format!("{}::", tcx.def_path_str(trait_def_id)) } else { @@ -881,8 +884,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else if let (Ok(snippet), false, false) = (tcx.sess.source_map().span_to_snippet(principal_span), dupes, shadows) { - let types: Vec<_> = - missing_assoc_types.iter().map(|item| format!("{} = Type", item.name)).collect(); + let types: Vec<_> = missing_assoc_types + .iter() + .map(|(item, _)| format!("{} = Type", item.name)) + .collect(); let code = if snippet.ends_with('>') { // The user wrote `Trait<'a>` or similar and we don't have a type we can // suggest, but at least we can clue them to the correct syntax @@ -914,15 +919,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if suggestions.len() != 1 || already_has_generics_args_suggestion { // We don't need this label if there's an inline suggestion, show otherwise. let mut names: FxIndexMap<_, usize> = FxIndexMap::default(); - for item in &missing_assoc_types { + for (item, _) in &missing_assoc_types { types_count += 1; *names.entry(item.name).or_insert(0) += 1; } let mut label = vec![]; - for item in &missing_assoc_types { + for (item, trait_ref) in &missing_assoc_types { let postfix = if names[&item.name] > 1 { - let trait_def_id = item.container_id(tcx); - format!(" (from trait `{}`)", tcx.def_path_str(trait_def_id)) + format!(" (from trait `{}`)", trait_ref.print_trait_sugared()) } else { String::new() }; |
