From 76802e31a131d2ac5933b8283a292735b6ab8366 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 3 May 2023 21:09:50 +0000 Subject: [PATCH] Error message for ambiguous RTN from super bounds --- compiler/rustc_hir_analysis/messages.ftl | 4 +++ .../rustc_hir_analysis/src/astconv/mod.rs | 12 +++++-- compiler/rustc_hir_analysis/src/errors.rs | 14 +++++++- compiler/rustc_middle/src/ty/print/pretty.rs | 6 ++++ .../super-method-bound-ambig.rs | 32 +++++++++++++++++++ .../super-method-bound-ambig.stderr | 19 +++++++++++ 6 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs create mode 100644 tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 703f168b766..2035b256daa 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -194,6 +194,10 @@ hir_analysis_return_type_notation_equality_bound = hir_analysis_return_type_notation_missing_method = cannot find associated function `{$assoc_name}` for `{$ty_name}` +hir_analysis_return_type_notation_conflicting_bound = + ambiguous associated function `{$assoc_name}` for `{$ty_name}` + .note = `{$assoc_name}` is declared in two supertraits: `{$first_bound}` and `{$second_bound}` + hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind} .label = not allowed in type signatures diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 7880a248cb0..9abb71d8b1a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -2083,8 +2083,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }; - if let Some(_conflicting_candidate) = matching_candidates.next() { - todo!() + if let Some(conflicting_candidate) = matching_candidates.next() { + return Err(self.tcx().sess.emit_err( + crate::errors::ReturnTypeNotationConflictingBound { + span, + ty_name: ty_name.to_string(), + assoc_name: assoc_name.name, + first_bound: candidate.print_only_trait_path(), + second_bound: conflicting_candidate.print_only_trait_path(), + }, + )); } Ok(candidate) diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 48330a94255..32c66b16fb9 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -6,7 +6,7 @@ use rustc_errors::{ MultiSpan, }; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, print::TraitRefPrintOnlyTraitPath, Ty}; use rustc_span::{symbol::Ident, Span, Symbol}; #[derive(Diagnostic)] @@ -516,6 +516,18 @@ pub(crate) struct ReturnTypeNotationMissingMethod { pub assoc_name: Symbol, } +#[derive(Diagnostic)] +#[diag(hir_analysis_return_type_notation_conflicting_bound)] +#[note] +pub(crate) struct ReturnTypeNotationConflictingBound<'tcx> { + #[primary_span] + pub span: Span, + pub ty_name: String, + pub assoc_name: Symbol, + pub first_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, + pub second_bound: ty::Binder<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, +} + #[derive(Diagnostic)] #[diag(hir_analysis_placeholder_not_allowed_item_signatures, code = "E0121")] pub(crate) struct PlaceholderNotAllowedItemSignatures { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 2aced27f7bb..32403d9a5e6 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2633,6 +2633,12 @@ macro_rules! define_print_and_forward_display { #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)] pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>); +impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintOnlyTraitPath<'tcx> { + fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { + self.to_string().into_diagnostic_arg() + } +} + impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self, f) diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs new file mode 100644 index 00000000000..028e526b5f5 --- /dev/null +++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs @@ -0,0 +1,32 @@ +// edition:2021 + +#![feature(async_fn_in_trait, return_type_notation)] +//~^ WARN the feature `return_type_notation` is incomplete + +trait Super1<'a> { + async fn test(); +} +impl Super1<'_> for () { + async fn test() {} +} + +trait Super2 { + async fn test(); +} +impl Super2 for () { + async fn test() {} +} + +trait Foo: for<'a> Super1<'a> + Super2 {} +impl Foo for () {} + +fn test() +where + T: Foo, + //~^ ERROR ambiguous associated function `test` for `Foo` +{ +} + +fn main() { + test::<()>(); +} diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr new file mode 100644 index 00000000000..5bc8dbde4bc --- /dev/null +++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr @@ -0,0 +1,19 @@ +warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes + --> $DIR/super-method-bound-ambig.rs:3:31 + | +LL | #![feature(async_fn_in_trait, return_type_notation)] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #109417 for more information + = note: `#[warn(incomplete_features)]` on by default + +error: ambiguous associated function `test` for `Foo` + --> $DIR/super-method-bound-ambig.rs:25:12 + | +LL | T: Foo, + | ^^^^^^^^^^^^ + | + = note: `test` is declared in two supertraits: `Super2` and `Super1<'a>` + +error: aborting due to previous error; 1 warning emitted +