From 49961947c8a830fc1d5d4ecc5916267a7e4bb6b0 Mon Sep 17 00:00:00 2001 From: Veera Date: Wed, 21 Feb 2024 16:46:57 -0500 Subject: [PATCH 1/3] Improve error messages for generics with default parameters Fixes #120785 --- .../src/infer/error_reporting/mod.rs | 21 ++++++++++++--- compiler/rustc_middle/src/ty/generics.rs | 27 +++++++++++++++++++ ...-for-generics-with-default-issue-120785.rs | 11 ++++++++ ...-generics-with-default-issue-120785.stderr | 27 +++++++++++++++++++ 4 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs create mode 100644 tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 911b2f16c8b05..38214ab72e696 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -1247,10 +1247,23 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { (&ty::Adt(def1, sub1), &ty::Adt(def2, sub2)) => { let did1 = def1.did(); let did2 = def2.did(); - let sub_no_defaults_1 = - self.tcx.generics_of(did1).own_args_no_defaults(self.tcx, sub1); - let sub_no_defaults_2 = - self.tcx.generics_of(did2).own_args_no_defaults(self.tcx, sub2); + + let generics1 = self.tcx.generics_of(did1); + let generics2 = self.tcx.generics_of(did2); + + let non_default_after_default = generics1 + .check_concrete_type_after_default(self.tcx, sub1) + || generics2.check_concrete_type_after_default(self.tcx, sub2); + let sub_no_defaults_1 = if non_default_after_default { + generics1.own_args(sub1) + } else { + generics1.own_args_no_defaults(self.tcx, sub1) + }; + let sub_no_defaults_2 = if non_default_after_default { + generics2.own_args(sub2) + } else { + generics2.own_args_no_defaults(self.tcx, sub2) + }; let mut values = (DiagStyledString::new(), DiagStyledString::new()); let path1 = self.tcx.def_path_str(did1); let path2 = self.tcx.def_path_str(did2); diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index c81d9dfbc7d60..4f75b7b42fb23 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -360,6 +360,33 @@ impl<'tcx> Generics { let own = &args[self.parent_count..][..self.params.len()]; if self.has_self && self.parent.is_none() { &own[1..] } else { own } } + + /// Returns true if a concrete type is specified after a default type. + /// For example, consider `struct T>(W, X)` + /// `T` will return true + /// `T` will return false + pub fn check_concrete_type_after_default( + &'tcx self, + tcx: TyCtxt<'tcx>, + args: &'tcx [ty::GenericArg<'tcx>], + ) -> bool { + let mut default_param_seen = false; + for param in self.params.iter() { + if param + .default_value(tcx) + .is_some_and(|default| default.instantiate(tcx, args) == args[param.index as usize]) + { + default_param_seen = true; + } else if default_param_seen + && param.default_value(tcx).is_some_and(|default| { + default.instantiate(tcx, args) != args[param.index as usize] + }) + { + return true; + } + } + false + } } /// Bounds on generics. diff --git a/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs new file mode 100644 index 0000000000000..a39c0049d01d0 --- /dev/null +++ b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs @@ -0,0 +1,11 @@ +struct What>(W, X); + +fn main() { + let mut b: What = What(5, vec![1, 2, 3]); + let c: What = What(1, String::from("meow")); + b = c; //~ ERROR mismatched types + + let mut e: What = What(5, vec![1, 2, 3]); + let f: What> = What(1, vec![String::from("meow")]); + e = f; //~ ERROR mismatched types +} diff --git a/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr new file mode 100644 index 0000000000000..60fd18b968ca5 --- /dev/null +++ b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr @@ -0,0 +1,27 @@ +error[E0308]: mismatched types + --> $DIR/clarify-error-for-generics-with-default-issue-120785.rs:6:9 + | +LL | let mut b: What = What(5, vec![1, 2, 3]); + | ----------- expected due to this type +LL | let c: What = What(1, String::from("meow")); +LL | b = c; + | ^ expected `What`, found `What` + | + = note: expected struct `What<_, Vec>` + found struct `What<_, String>` + +error[E0308]: mismatched types + --> $DIR/clarify-error-for-generics-with-default-issue-120785.rs:10:9 + | +LL | let mut e: What = What(5, vec![1, 2, 3]); + | ----------- expected due to this type +LL | let f: What> = What(1, vec![String::from("meow")]); +LL | e = f; + | ^ expected `What`, found `What>` + | + = note: expected struct `What<_, Vec>` + found struct `What<_, Vec>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. From 3ba50b36e7a20036c7b2c47ab551508b923b0004 Mon Sep 17 00:00:00 2001 From: Veera Date: Thu, 22 Feb 2024 21:37:11 -0500 Subject: [PATCH 2/3] Avoid code duplication --- compiler/rustc_middle/src/ty/generics.rs | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 4f75b7b42fb23..2630b96869bae 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -372,17 +372,14 @@ impl<'tcx> Generics { ) -> bool { let mut default_param_seen = false; for param in self.params.iter() { - if param - .default_value(tcx) - .is_some_and(|default| default.instantiate(tcx, args) == args[param.index as usize]) + if let Some(inst) = + param.default_value(tcx).map(|default| default.instantiate(tcx, args)) { - default_param_seen = true; - } else if default_param_seen - && param.default_value(tcx).is_some_and(|default| { - default.instantiate(tcx, args) != args[param.index as usize] - }) - { - return true; + if inst == args[param.index as usize] { + default_param_seen = true; + } else if default_param_seen { + return true; + } } } false From cc13f8278f22243a6ecd82d062c4740787a0fc51 Mon Sep 17 00:00:00 2001 From: Veera Date: Fri, 23 Feb 2024 13:22:14 -0500 Subject: [PATCH 3/3] Update item order in test --- ...error-for-generics-with-default-issue-120785.rs | 6 +++--- ...r-for-generics-with-default-issue-120785.stderr | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs index a39c0049d01d0..7a923179d3b73 100644 --- a/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs +++ b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.rs @@ -5,7 +5,7 @@ fn main() { let c: What = What(1, String::from("meow")); b = c; //~ ERROR mismatched types - let mut e: What = What(5, vec![1, 2, 3]); - let f: What> = What(1, vec![String::from("meow")]); - e = f; //~ ERROR mismatched types + let mut f: What> = What(1, vec![String::from("meow")]); + let e: What = What(5, vec![1, 2, 3]); + f = e; //~ ERROR mismatched types } diff --git a/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr index 60fd18b968ca5..d2b3397fbcb03 100644 --- a/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr +++ b/tests/ui/type/clarify-error-for-generics-with-default-issue-120785.stderr @@ -13,14 +13,14 @@ LL | b = c; error[E0308]: mismatched types --> $DIR/clarify-error-for-generics-with-default-issue-120785.rs:10:9 | -LL | let mut e: What = What(5, vec![1, 2, 3]); - | ----------- expected due to this type -LL | let f: What> = What(1, vec![String::from("meow")]); -LL | e = f; - | ^ expected `What`, found `What>` +LL | let mut f: What> = What(1, vec![String::from("meow")]); + | ------------------------ expected due to this type +LL | let e: What = What(5, vec![1, 2, 3]); +LL | f = e; + | ^ expected `What>`, found `What` | - = note: expected struct `What<_, Vec>` - found struct `What<_, Vec>` + = note: expected struct `What<_, Vec>` + found struct `What<_, Vec>` error: aborting due to 2 previous errors