Skip to content

Commit

Permalink
Rollup merge of rust-lang#98022 - compiler-errors:erroneous-borrowck-…
Browse files Browse the repository at this point in the history
…span, r=oli-obk

Fix erroneous span for borrowck error

I am not confident that this is the correct fix, but it does the job. Open to suggestions for a real fix instead.

Fixes rust-lang#97997

The issue is that we pass a [dummy location](https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/mir/visit.rs.html#302) when type-checking the ["required consts"](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/struct.Body.html#structfield.required_consts) that are needed by the MIR body during borrowck. This means that when we fail to evaluate the constant, we use the span of `bb0[0]`, instead of the actual span of the constant.

There are quite a few other places that use `START_BLOCK.start_location()`, `Location::START`, etc. when calling for a random/unspecified `Location` value. This is because, unlike (for example) `Span`, we don't have a dummy/miscellaneous value to use instead. I would appreciate guidance (either in this PR, or a follow-up) on what needs to be done to clean this up in general.
  • Loading branch information
JohnTitor authored Jun 21, 2022
2 parents 42dcf70 + ccf6124 commit 895b50f
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 11 deletions.
24 changes: 14 additions & 10 deletions compiler/rustc_borrowck/src/type_check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,12 +357,20 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
.add_element(live_region_vid, location);
});

// HACK(compiler-errors): Constants that are gathered into Body.required_consts
// have their locations erased...
let locations = if location != Location::START {
location.to_locations()
} else {
Locations::All(constant.span)
};

if let Some(annotation_index) = constant.user_ty {
if let Err(terr) = self.cx.relate_type_and_user_type(
constant.literal.ty(),
ty::Variance::Invariant,
&UserTypeProjection { base: annotation_index, projs: vec![] },
location.to_locations(),
locations,
ConstraintCategory::Boring,
) {
let annotation = &self.cx.user_type_annotations[annotation_index];
Expand Down Expand Up @@ -390,12 +398,9 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
promoted: &Body<'tcx>,
ty,
san_ty| {
if let Err(terr) = verifier.cx.eq_types(
ty,
san_ty,
location.to_locations(),
ConstraintCategory::Boring,
) {
if let Err(terr) =
verifier.cx.eq_types(ty, san_ty, locations, ConstraintCategory::Boring)
{
span_mirbug!(
verifier,
promoted,
Expand All @@ -416,7 +421,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
} else {
if let Err(terr) = self.cx.fully_perform_op(
location.to_locations(),
locations,
ConstraintCategory::Boring,
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
constant.literal.ty(),
Expand All @@ -435,7 +440,6 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
}
} else if let Some(static_def_id) = constant.check_static_ptr(tcx) {
let unnormalized_ty = tcx.type_of(static_def_id);
let locations = location.to_locations();
let normalized_ty = self.cx.normalize(unnormalized_ty, locations);
let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty;

Expand All @@ -454,7 +458,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
self.cx.normalize_and_prove_instantiated_predicates(
def_id,
instantiated_predicates,
location.to_locations(),
locations,
);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/hrtb/hrtb-just-for-static.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ error: implementation of `Foo` is not general enough
--> $DIR/hrtb-just-for-static.rs:24:5
|
LL | want_hrtb::<StaticInt>()
| ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
| ^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`...
= note: ...but it actually implements `Foo<&'static isize>`
Expand Down
16 changes: 16 additions & 0 deletions src/test/ui/nll/issue-97997.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
trait Foo {
const ASSOC: bool = true;
}
impl<T> Foo for fn(T) {}

fn foo(_x: i32) {}

fn impls_foo<T: Foo>(_x: T) {}

fn main() {
impls_foo(foo as fn(i32));

<fn(&u8) as Foo>::ASSOC;
//~^ ERROR implementation of `Foo` is not general enough
//~| ERROR implementation of `Foo` is not general enough
}
20 changes: 20 additions & 0 deletions src/test/ui/nll/issue-97997.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
error: implementation of `Foo` is not general enough
--> $DIR/issue-97997.rs:13:5
|
LL | <fn(&u8) as Foo>::ASSOC;
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)`
= note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`

error: implementation of `Foo` is not general enough
--> $DIR/issue-97997.rs:13:5
|
LL | <fn(&u8) as Foo>::ASSOC;
| ^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
|
= note: `Foo` would have to be implemented for the type `for<'r> fn(&'r u8)`
= note: ...but `Foo` is actually implemented for the type `fn(&'0 u8)`, for some specific lifetime `'0`

error: aborting due to 2 previous errors

0 comments on commit 895b50f

Please sign in to comment.