Skip to content

Commit

Permalink
track spans for assumed_wf_types
Browse files Browse the repository at this point in the history
  • Loading branch information
lcnr committed Jun 29, 2023
1 parent 75726ca commit e674a8f
Show file tree
Hide file tree
Showing 15 changed files with 70 additions and 63 deletions.
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4157,6 +4157,7 @@ dependencies = [
name = "rustc_ty_utils"
version = "0.0.0"
dependencies = [
"itertools",
"rustc_data_structures",
"rustc_errors",
"rustc_fluent_macro",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ fn check_opaque_meets_bounds<'tcx>(
if tcx.def_kind(tcx.parent(def_id.to_def_id())) == DefKind::OpaqueTy => {}
// Can have different predicates to their defining use
hir::OpaqueTyOrigin::TyAlias { .. } => {
let wf_tys = ocx.assumed_wf_types(param_env, span, def_id);
let wf_tys = ocx.assumed_wf_types(param_env, def_id);
let implied_bounds = infcx.implied_bounds_tys(param_env, def_id, wf_tys);
let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds);
let _ = ocx.resolve_regions_and_report_errors(defining_use_anchor, &outlives_env);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2037,7 +2037,7 @@ pub(super) fn check_type_bounds<'tcx>(
_ => bug!(),
}
};
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty_def_id);
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl_ty_def_id);

let normalize_cause = ObligationCause::new(
impl_ty_span,
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_hir_analysis/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
}
f(&mut wfcx);

let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, span, body_def_id);
let assumed_wf_types = wfcx.ocx.assumed_wf_types(param_env, body_def_id);
let implied_bounds = infcx.implied_bounds_tys(param_env, body_def_id, assumed_wf_types);

let errors = wfcx.select_all_or_error();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ fn get_impl_substs(
let ocx = ObligationCtxt::new(infcx);
let param_env = tcx.param_env(impl1_def_id);

let assumed_wf_types =
ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
let assumed_wf_types = ocx.assumed_wf_types(param_env, impl1_def_id);

let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id);
let impl1_span = tcx.def_span(impl1_def_id);
Expand Down
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 @@ -881,7 +881,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::List<Ty<'tcx>> {
query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) }
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/traits/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ fn prove_negated_obligation<'tcx>(
let body_def_id = body_def_id.as_local().unwrap_or(CRATE_DEF_ID);

let ocx = ObligationCtxt::new(&infcx);
let wf_tys = ocx.assumed_wf_types(param_env, DUMMY_SP, body_def_id);
let wf_tys = ocx.assumed_wf_types(param_env, body_def_id);
let outlives_env = OutlivesEnvironment::with_bounds(
param_env,
infcx.implied_bounds_tys(param_env, body_def_id, wf_tys),
Expand Down
7 changes: 2 additions & 5 deletions compiler/rustc_trait_selection/src/traits/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ use rustc_middle::ty::ToPredicate;
use rustc_middle::ty::TypeFoldable;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_session::config::TraitSolver;
use rustc_span::Span;

pub trait TraitEngineExt<'tcx> {
fn new(infcx: &InferCtxt<'tcx>) -> Box<Self>;
Expand Down Expand Up @@ -223,14 +222,11 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
pub fn assumed_wf_types(
&self,
param_env: ty::ParamEnv<'tcx>,
span: Span,
def_id: LocalDefId,
) -> FxIndexSet<Ty<'tcx>> {
let tcx = self.infcx.tcx;
let assumed_wf_types = tcx.assumed_wf_types(def_id);
let mut implied_bounds = FxIndexSet::default();
let cause = ObligationCause::misc(span, def_id);
for ty in assumed_wf_types {
for &(ty, span) in tcx.assumed_wf_types(def_id) {
// 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 @@ -243,6 +239,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
// sound and then uncomment this line again.

// implied_bounds.insert(ty);
let cause = ObligationCause::misc(span, def_id);
let normalized = self.normalize(&cause, param_env, ty);
implied_bounds.insert(normalized);
}
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_ty_utils/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2021"

[dependencies]
tracing = "0.1"
itertools = "0.10"
rustc_middle = { path = "../rustc_middle" }
rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
Expand Down
76 changes: 56 additions & 20 deletions compiler/rustc_ty_utils/src/implied_bounds.rs
Original file line number Diff line number Diff line change
@@ -1,45 +1,56 @@
use rustc_hir::{def::DefKind, def_id::DefId};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::LocalDefId;
use rustc_middle::query::Providers;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_span::Span;
use std::iter;

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

fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] {
match tcx.def_kind(def_id) {
DefKind::Fn => {
let sig = tcx.fn_sig(def_id).subst_identity();
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
liberated_sig.inputs_and_output
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
tcx.arena.alloc_from_iter(itertools::zip_eq(
liberated_sig.inputs_and_output,
fn_sig_spans(tcx, def_id),
))
}
DefKind::AssocFn => {
let sig = tcx.fn_sig(def_id).subst_identity();
let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
let liberated_sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
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.mk_type_list(&assumed_wf_types)
tcx.assumed_wf_types(tcx.local_parent(def_id)).into();
assumed_wf_types.extend(itertools::zip_eq(
liberated_sig.inputs_and_output,
fn_sig_spans(tcx, def_id),
));
tcx.arena.alloc_slice(&assumed_wf_types)
}
DefKind::Impl { .. } => {
match tcx.impl_trait_ref(def_id) {
Some(trait_ref) => {
let types: Vec<_> = trait_ref.skip_binder().substs.types().collect();
tcx.mk_type_list(&types)
}
// Only the impl self type
None => tcx.mk_type_list(&[tcx.type_of(def_id).subst_identity()]),
}
// Trait arguments and the self type for trait impls or only the self type for
// inherent impls.
let tys = match tcx.impl_trait_ref(def_id) {
Some(trait_ref) => trait_ref.skip_binder().substs.types().collect(),
None => vec![tcx.type_of(def_id).subst_identity()],
};

let mut impl_spans = impl_spans(tcx, def_id);
tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap())))
}
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
DefKind::OpaqueTy => match tcx.def_kind(tcx.parent(def_id)) {
DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) {
DefKind::TyAlias => ty::List::empty(),
DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)),
// Nested opaque types only occur in associated types:
// ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; `
// assumed_wf_types should include those of `Opaque<T>`, `Opaque<T>` itself
// and `&'static T`.
DefKind::OpaqueTy => bug!("unimplemented implied bounds for neseted opaque types"),
DefKind::OpaqueTy => bug!("unimplemented implied bounds for nested opaque types"),
def_kind @ _ => {
bug!("unimplemented implied bounds for opaque types with parent {def_kind:?}")
}
Expand Down Expand Up @@ -72,3 +83,28 @@ fn assumed_wf_types(tcx: TyCtxt<'_>, def_id: DefId) -> &ty::List<Ty<'_>> {
| DefKind::Generator => ty::List::empty(),
}
}

fn fn_sig_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
let node = tcx.hir().get(tcx.local_def_id_to_hir_id(def_id));
if let Some(decl) = node.fn_decl() {
decl.inputs.iter().map(|ty| ty.span).chain(iter::once(decl.output.span()))
} else {
bug!("unexpected item for fn {def_id:?}: {node:?}")
}
}

fn impl_spans(tcx: TyCtxt<'_>, def_id: LocalDefId) -> impl Iterator<Item = Span> + '_ {
let item = tcx.hir().expect_item(def_id);
if let hir::ItemKind::Impl(impl_) = item.kind {
let trait_args = impl_
.of_trait
.into_iter()
.flat_map(|trait_ref| trait_ref.path.segments.last().unwrap().args().args)
.map(|arg| arg.span());
let dummy_spans_for_default_args =
impl_.of_trait.into_iter().flat_map(|trait_ref| iter::repeat(trait_ref.path.span));
iter::once(impl_.self_ty.span).chain(trait_args).chain(dummy_spans_for_default_args)
} else {
bug!("unexpected item for impl {def_id:?}: {item:?}")
}
}
4 changes: 2 additions & 2 deletions tests/ui/associated-inherent-types/issue-109789.stderr
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
error[E0308]: mismatched types
--> $DIR/issue-109789.rs:18:1
--> $DIR/issue-109789.rs:18:11
|
LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected struct `Foo<fn(&'static ())>`
found struct `Foo<for<'a> fn(&'a ())>`
Expand Down
1 change: 0 additions & 1 deletion tests/ui/issues/issue-35570.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ 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: 1 addition & 11 deletions tests/ui/issues/issue-35570.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,6 @@ 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[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
error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ 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,21 +9,6 @@ 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[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
error: aborting due to previous error

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

0 comments on commit e674a8f

Please sign in to comment.