diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 904abe45a231b..cf3017842952b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -571,6 +571,10 @@ impl<'hir> Generics<'hir> { self.params.iter().find(|¶m| name == param.name.ident().name) } + pub fn get_with_local_def_id(&self, id: LocalDefId) -> Option<&GenericParam<'hir>> { + self.params.iter().find(|¶m| id == param.def_id) + } + /// If there are generic parameters, return where to introduce a new one. pub fn span_for_lifetime_suggestion(&self) -> Option { if let Some(first) = self.params.first() diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d0687dfc6fd25..ee96363fe8df8 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -201,9 +201,10 @@ fn msg_span_from_named_region<'tcx>( match *region { ty::ReEarlyParam(ref br) => { let scope = region.free_region_binding_scope(tcx).expect_local(); - let span = if let Some(param) = - tcx.hir().get_generics(scope).and_then(|generics| generics.get_named(br.name)) - { + let span = if let Some(param) = tcx.hir().get_generics(scope).and_then(|generics| { + let local_def_id = br.def_id.expect_local(); + generics.get_with_local_def_id(local_def_id) + }) { param.span } else { tcx.def_span(scope) diff --git a/tests/ui/inference/unnamed-lifetime-span-mixup-125143.rs b/tests/ui/inference/unnamed-lifetime-span-mixup-125143.rs new file mode 100644 index 0000000000000..c9572471607d7 --- /dev/null +++ b/tests/ui/inference/unnamed-lifetime-span-mixup-125143.rs @@ -0,0 +1,42 @@ +struct X; + +// Test that the error correctly differentiate between the two unnamed lifetimes +impl std::ops::Add<&X> for &X { + type Output = X; + + fn add(self, _rhs: Self) -> Self::Output { + X + } +} +//~^^^^ ERROR method not compatible with trait + +// Test that the error correctly differentiate between named and the unnamed lifetimes +impl<'a> std::ops::Mul<&'a X> for &X { + type Output = X; + + fn mul(self, _rhs: Self) -> Self::Output { + X + } +} +//~^^^^ ERROR method not compatible with trait + +// Test that the error correctly differentiate between named and the unnamed lifetimes +impl<'a> std::ops::Sub<&X> for &'a X { + type Output = X; + + fn sub(self, _rhs: Self) -> Self::Output { + X + } +} +//~^^^^ ERROR method not compatible with trait + +// This should pass since the lifetime subtyping will pass typecheck +impl<'a, 'b> std::ops::Div<&'a X> for &'b X where 'a : 'b { + type Output = X; + + fn div(self, _rhs: Self) -> Self::Output { + X + } +} + +fn main() {} diff --git a/tests/ui/inference/unnamed-lifetime-span-mixup-125143.stderr b/tests/ui/inference/unnamed-lifetime-span-mixup-125143.stderr new file mode 100644 index 0000000000000..a81c14b47c14f --- /dev/null +++ b/tests/ui/inference/unnamed-lifetime-span-mixup-125143.stderr @@ -0,0 +1,60 @@ +error[E0308]: method not compatible with trait + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:7:5 + | +LL | fn add(self, _rhs: Self) -> Self::Output { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&X, &X) -> X` + found signature `fn(&X, &X) -> X` +note: the anonymous lifetime as defined here... + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:4:20 + | +LL | impl std::ops::Add<&X> for &X { + | ^ +note: ...does not necessarily outlive the anonymous lifetime as defined here + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:4:28 + | +LL | impl std::ops::Add<&X> for &X { + | ^ + +error[E0308]: method not compatible with trait + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:17:5 + | +LL | fn mul(self, _rhs: Self) -> Self::Output { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&X, &'a X) -> X` + found signature `fn(&X, &X) -> X` +note: the lifetime `'a` as defined here... + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:14:6 + | +LL | impl<'a> std::ops::Mul<&'a X> for &X { + | ^^ +note: ...does not necessarily outlive the anonymous lifetime as defined here + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:14:35 + | +LL | impl<'a> std::ops::Mul<&'a X> for &X { + | ^ + +error[E0308]: method not compatible with trait + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:27:5 + | +LL | fn sub(self, _rhs: Self) -> Self::Output { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected signature `fn(&'a X, &X) -> X` + found signature `fn(&'a X, &'a X) -> X` +note: the anonymous lifetime as defined here... + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:24:24 + | +LL | impl<'a> std::ops::Sub<&X> for &'a X { + | ^ +note: ...does not necessarily outlive the lifetime `'a` as defined here + --> $DIR/unnamed-lifetime-span-mixup-125143.rs:24:6 + | +LL | impl<'a> std::ops::Sub<&X> for &'a X { + | ^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0308`.