diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 85d9db7ee7473..5610067cd871e 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -219,11 +219,19 @@ impl<'tcx> Generics { /// Returns the `GenericParamDef` with the given index. pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { + self.try_param_at(param_index, tcx).expect("bug: invalid parameter index") + } + + pub fn try_param_at( + &'tcx self, + param_index: usize, + tcx: TyCtxt<'tcx>, + ) -> Option<&'tcx GenericParamDef> { if let Some(index) = param_index.checked_sub(self.parent_count) { - &self.own_params[index] + self.own_params.get(index) } else { tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) - .param_at(param_index, tcx) + .try_param_at(param_index, tcx) } } @@ -260,6 +268,16 @@ impl<'tcx> Generics { } } + pub fn try_type_param( + &'tcx self, + param: ParamTy, + tcx: TyCtxt<'tcx>, + ) -> Option<&'tcx GenericParamDef> { + self.try_param_at(param.index as usize, tcx).and_then(|param| { + if matches!(param.kind, GenericParamDefKind::Type { .. }) { Some(param) } else { None } + }) + } + /// Returns the `GenericParamDef` associated with this `ParamConst`. pub fn const_param(&'tcx self, param: ParamConst, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { let param = self.param_at(param.index as usize, tcx); diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index 514615735a507..80c55989c54bc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -241,14 +241,17 @@ impl Trait for X { } (ty::Param(p), _) | (_, ty::Param(p)) => { let generics = tcx.generics_of(body_owner_def_id); - let p_span = tcx.def_span(generics.type_param(p, tcx).def_id); - let expected = match (values.expected.kind(), values.found.kind()) { - (ty::Param(_), _) => "expected ", - (_, ty::Param(_)) => "found ", - _ => "", - }; - if !sp.contains(p_span) { - diag.span_label(p_span, format!("{expected}this type parameter")); + let type_param = generics.try_type_param(p, tcx); + if let Some(type_param) = type_param { + let p_span = tcx.def_span(type_param.def_id); + let expected = match (values.expected.kind(), values.found.kind()) { + (ty::Param(_), _) => "expected ", + (_, ty::Param(_)) => "found ", + _ => "", + }; + if !sp.contains(p_span) { + diag.span_label(p_span, format!("{expected}this type parameter")); + } } } (ty::Alias(ty::Projection | ty::Inherent, proj_ty), _) diff --git a/tests/ui/generics/generic-param-issue-137865.rs b/tests/ui/generics/generic-param-issue-137865.rs new file mode 100644 index 0000000000000..fa0a1900e330b --- /dev/null +++ b/tests/ui/generics/generic-param-issue-137865.rs @@ -0,0 +1,9 @@ +//@ edition: 2021 + + +trait Foo { + type Assoc; //~ ERROR: `Self` is forbidden as the type of a const generic parameter + fn foo() -> Self::Assoc<3>; //~ ERROR: mismatched types +} + +fn main() {} diff --git a/tests/ui/generics/generic-param-issue-137865.stderr b/tests/ui/generics/generic-param-issue-137865.stderr new file mode 100644 index 0000000000000..c0bd8a5e557d6 --- /dev/null +++ b/tests/ui/generics/generic-param-issue-137865.stderr @@ -0,0 +1,20 @@ +error: `Self` is forbidden as the type of a const generic parameter + --> $DIR/generic-param-issue-137865.rs:5:25 + | +LL | type Assoc; + | ^^^^ + | + = note: the only supported types are integers, `bool`, and `char` + +error[E0308]: mismatched types + --> $DIR/generic-param-issue-137865.rs:6:29 + | +LL | fn foo() -> Self::Assoc<3>; + | ^ expected type parameter `Self`, found integer + | + = note: expected type parameter `Self` + found type `{integer}` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`.