Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve spans of non-WF implied bound types #106582

Merged
merged 3 commits into from
Jan 9, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Don't store spans in assumed_wf_types actually
  • Loading branch information
compiler-errors committed Jan 8, 2023
commit e77e8eb9455264b70eb4344a404243b7c012db08
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,7 @@ rustc_queries! {
///
/// Note that we've liberated the late bound regions of function signatures, so
/// this can not be used to check whether these types are well formed.
query assumed_wf_types(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] {
query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
let assumed_wf_types = tcx.assumed_wf_types(def_id);
let mut implied_bounds = FxIndexSet::default();
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
for &(ty, ty_span) in assumed_wf_types {
let span = if ty_span.is_dummy() { span } else { ty_span };
let cause = ObligationCause::misc(span, hir_id);
for ty in assumed_wf_types {
// FIXME(@lcnr): rustc currently does not check wf for types
// pre-normalization, meaning that implied bounds are sometimes
// incorrect. See #100910 for more details.
Expand All @@ -205,7 +205,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
// sound and then uncomment this line again.

// implied_bounds.insert(ty);
let normalized = self.normalize(&ObligationCause::misc(span, hir_id), param_env, ty);
let normalized = self.normalize(&cause, param_env, ty);
implied_bounds.insert(normalized);
}
implied_bounds
Expand Down
67 changes: 10 additions & 57 deletions compiler/rustc_ty_utils/src/implied_bounds.rs
Original file line number Diff line number Diff line change
@@ -1,80 +1,33 @@
use crate::rustc_middle::ty::DefIdTree;
use rustc_hir::{self as hir, def::DefKind, def_id::DefId};
use rustc_hir::{def::DefKind, def_id::DefId};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::{Span, DUMMY_SP};

pub fn provide(providers: &mut ty::query::Providers) {
*providers = ty::query::Providers { assumed_wf_types, ..*providers };
}

fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &[(Ty<'_>, Span)] {
fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
match tcx.def_kind(def_id) {
DefKind::Fn => {
let sig = tcx.fn_sig(def_id);
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
if let Some(node) = tcx.hir().get_if_local(def_id)
&& let Some(decl) = node.fn_decl()
{
assert_eq!(decl.inputs.len(), liberated_sig.inputs().len());
tcx.arena.alloc_from_iter(std::iter::zip(
liberated_sig.inputs_and_output,
decl.inputs.iter().map(|ty| ty.span).chain([decl.output.span()]),
))
} else {
tcx.arena.alloc_from_iter(
liberated_sig.inputs_and_output.iter().map(|ty| (ty, DUMMY_SP)),
)
}
liberated_sig.inputs_and_output
}
DefKind::AssocFn => {
let sig = tcx.fn_sig(def_id);
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
let assumed_wf_types = tcx.assumed_wf_types(tcx.parent(def_id));
if let Some(node) = tcx.hir().get_if_local(def_id)
&& let Some(decl) = node.fn_decl()
{
assert_eq!(decl.inputs.len(), liberated_sig.inputs().len());
tcx.arena.alloc_from_iter(assumed_wf_types.iter().copied().chain(std::iter::zip(
liberated_sig.inputs_and_output,
decl.inputs.iter().map(|ty| ty.span).chain([decl.output.span()]),
)))
} else {
tcx.arena.alloc_from_iter(assumed_wf_types.iter().copied().chain(
liberated_sig.inputs_and_output.iter().map(|ty| (ty, DUMMY_SP)),
))
}
let mut assumed_wf_types: Vec<_> =
tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
assumed_wf_types.extend(liberated_sig.inputs_and_output);
tcx.intern_type_list(&assumed_wf_types)
}
DefKind::Impl => match tcx.impl_trait_ref(def_id) {
Some(trait_ref) => {
let types: Vec<_> = trait_ref.substs.types().collect();
let self_span = if let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(impl_),
..
})) = tcx.hir().get_if_local(def_id)
{
impl_.self_ty.span
} else {
DUMMY_SP
};
tcx.arena.alloc_from_iter(std::iter::zip(
types,
// FIXME: reliable way of getting trait ref substs...
[self_span].into_iter().chain(std::iter::repeat(DUMMY_SP)),
))
tcx.intern_type_list(&types)
}
// Only the impl self type
None => {
let span = if let Some(hir::Node::Item(hir::Item {
kind: hir::ItemKind::Impl(impl_),
..
})) = tcx.hir().get_if_local(def_id)
{
impl_.self_ty.span
} else {
DUMMY_SP
};
tcx.arena.alloc_from_iter([(tcx.type_of(def_id), span)])
}
None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
},
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
DefKind::Mod
Expand Down Expand Up @@ -103,6 +56,6 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &[(Ty<'_>, Span)] {
| DefKind::LifetimeParam
| DefKind::GlobalAsm
| DefKind::Closure
| DefKind::Generator => &[],
| DefKind::Generator => ty::List::empty(),
}
}
1 change: 1 addition & 0 deletions src/test/ui/issues/issue-35570.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ trait Trait2<'a> {

fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
//~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
//~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
let _e: (usize, usize) = unsafe{mem::transmute(param)};
}

Expand Down
12 changes: 11 additions & 1 deletion src/test/ui/issues/issue-35570.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
| ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`

error: aborting due to previous error
error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
--> $DIR/issue-35570.rs:8:1
|
LL | / fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
LL | |
LL | |
LL | | let _e: (usize, usize) = unsafe{mem::transmute(param)};
LL | | }
| |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ trait Trait2<'a, 'b> {
// do not infer that.
fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
//~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
//~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
{
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,21 @@ help: consider restricting type parameter `T`
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
| ++++++++++++++++++++++++

error: aborting due to previous error
error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
--> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
|
LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
LL | |
LL | |
LL | | {
LL | | }
| |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
|
help: consider restricting type parameter `T`
|
LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
| ++++++++++++++++++++++++

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.