From ea9a253ff1e0a24e6439c122960f9a17a6e8d58d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 24 Jan 2025 04:06:47 +0000 Subject: [PATCH] Properly report error when object type param default references self --- .../src/error_codes/E0393.md | 12 +++++------ compiler/rustc_hir_analysis/messages.ftl | 8 +++++++- .../src/hir_ty_lowering/dyn_compatibility.rs | 8 +------- .../default-param-self-projection.rs | 17 ++++++++++++++++ .../default-param-self-projection.stderr | 18 +++++++++++++++++ tests/ui/error-codes/E0393.stderr | 2 +- tests/ui/issues/issue-22370.stderr | 2 +- ...onicalize-fresh-infer-vars-issue-103626.rs | 1 + ...alize-fresh-infer-vars-issue-103626.stderr | 20 +++++++++++++++++-- .../unspecified-self-in-trait-ref.stderr | 2 +- ...parameter-defaults-referencing-Self.stderr | 2 +- 11 files changed, 71 insertions(+), 21 deletions(-) create mode 100644 tests/ui/dyn-compatibility/default-param-self-projection.rs create mode 100644 tests/ui/dyn-compatibility/default-param-self-projection.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0393.md b/compiler/rustc_error_codes/src/error_codes/E0393.md index 50225b25163fe..c72608159051e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0393.md +++ b/compiler/rustc_error_codes/src/error_codes/E0393.md @@ -3,12 +3,10 @@ A type parameter which references `Self` in its default value was not specified. Erroneous code example: ```compile_fail,E0393 -trait A {} +trait A {} -fn together_we_will_rule_the_galaxy(son: &A) {} -// error: the type parameter `T` must be explicitly specified in an -// object type because its default value `Self` references the -// type `Self` +fn together_we_will_rule_the_galaxy(son: &dyn A) {} +// error: the type parameter `T` must be explicitly specified ``` A trait object is defined over a single, fully-defined trait. With a regular @@ -23,7 +21,7 @@ disallowed. Making the trait concrete by explicitly specifying the value of the defaulted parameter will fix this issue. Fixed example: ``` -trait A {} +trait A {} -fn together_we_will_rule_the_galaxy(son: &A) {} // Ok! +fn together_we_will_rule_the_galaxy(son: &dyn A) {} // Ok! ``` diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 512d379687bcf..be4004f5904cc 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -353,7 +353,13 @@ hir_analysis_missing_type_params = [one] reference *[other] references } to {$parameters} - .note = because of the default `Self` reference, type parameters must be specified on object types + .note = because the parameter {$parameterCount -> + [one] default references + *[other] defaults reference + } `Self`, the {$parameterCount -> + [one] parameter + *[other] parameters + } must be specified on the object type hir_analysis_multiple_relaxed_default_bounds = type parameter has more than one relaxed default bound, only one is supported 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 72ad190df7ee1..e59ff02642cf1 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 @@ -237,16 +237,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Skip `Self` .skip(1) .map(|(index, arg)| { - if arg == dummy_self.into() { + if arg.walk().any(|arg| arg == dummy_self.into()) { let param = &generics.own_params[index]; missing_type_params.push(param.name); Ty::new_misc_error(tcx).into() - } else if arg.walk().any(|arg| arg == dummy_self.into()) { - let guar = self.dcx().span_delayed_bug( - span, - "trait object trait bounds reference `Self`", - ); - replace_dummy_self_with_error(tcx, arg, guar) } else { arg } diff --git a/tests/ui/dyn-compatibility/default-param-self-projection.rs b/tests/ui/dyn-compatibility/default-param-self-projection.rs new file mode 100644 index 0000000000000..a440cd735daba --- /dev/null +++ b/tests/ui/dyn-compatibility/default-param-self-projection.rs @@ -0,0 +1,17 @@ +trait A::E> {} + +trait D { + type E; +} + +impl A<()> for () {} +impl D for () { + type E = (); +} + +fn f() { + let B: &dyn A = &(); + //~^ ERROR the type parameter `C` must be explicitly specified +} + +fn main() {} diff --git a/tests/ui/dyn-compatibility/default-param-self-projection.stderr b/tests/ui/dyn-compatibility/default-param-self-projection.stderr new file mode 100644 index 0000000000000..ea252a99b0480 --- /dev/null +++ b/tests/ui/dyn-compatibility/default-param-self-projection.stderr @@ -0,0 +1,18 @@ +error[E0393]: the type parameter `C` must be explicitly specified + --> $DIR/default-param-self-projection.rs:13:17 + | +LL | trait A::E> {} + | --------------------------- type parameter `C` must be specified for this +... +LL | let B: &dyn A = &(); + | ^ + | + = note: because the parameter default references `Self`, the parameter must be specified on the object type +help: set the type parameter to the desired type + | +LL | let B: &dyn A = &(); + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/error-codes/E0393.stderr b/tests/ui/error-codes/E0393.stderr index 489398b7be59e..4847aa2508dad 100644 --- a/tests/ui/error-codes/E0393.stderr +++ b/tests/ui/error-codes/E0393.stderr @@ -7,7 +7,7 @@ LL | LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} | ^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} diff --git a/tests/ui/issues/issue-22370.stderr b/tests/ui/issues/issue-22370.stderr index 3dc060963f920..b02d867eb7dd9 100644 --- a/tests/ui/issues/issue-22370.stderr +++ b/tests/ui/issues/issue-22370.stderr @@ -7,7 +7,7 @@ LL | LL | fn f(a: &dyn A) {} | ^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn f(a: &dyn A) {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs index 6dcfc754448b6..6fcd67b4950f7 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs @@ -10,6 +10,7 @@ fn w<'a, T: 'a, F: Fn(&'a T)>() { let b: &dyn FromResidual = &(); //~^ ERROR: the trait `FromResidual` is not dyn compatible //~| ERROR: the trait `FromResidual` is not dyn compatible + //~| ERROR the type parameter `R` must be explicitly specified } fn main() {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index 7040c067f5c20..ae3762704c6ac 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -1,3 +1,18 @@ +error[E0393]: the type parameter `R` must be explicitly specified + --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17 + | +LL | trait FromResidual::Residual> { + | ----------------------------------------------- type parameter `R` must be specified for this +... +LL | let b: &dyn FromResidual = &(); + | ^^^^^^^^^^^^ + | + = note: because the parameter default references `Self`, the parameter must be specified on the object type +help: set the type parameter to the desired type + | +LL | let b: &dyn FromResidual = &(); + | +++ + error[E0038]: the trait `FromResidual` is not dyn compatible --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32 | @@ -45,6 +60,7 @@ help: alternatively, consider constraining `from_residual` so it does not apply LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0038, E0393. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr index 22dceadc10de9..6f5ae786de6bc 100644 --- a/tests/ui/traits/unspecified-self-in-trait-ref.stderr +++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr @@ -97,7 +97,7 @@ LL | pub trait Bar { LL | let e = Bar::::lol(); | ^^^^^^^^^^^^ missing reference to `A` | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type error: aborting due to 5 previous errors; 5 warnings emitted diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr index c81405f03f8fa..23f10c9262c7b 100644 --- a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr +++ b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr @@ -7,7 +7,7 @@ LL | trait Foo { LL | fn foo(x: &dyn Foo) { } | ^^^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn foo(x: &dyn Foo) { }