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

do not propagate inferred bounds on trait objects if they involve Self #56003

Merged
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 6 additions & 1 deletion src/librustc/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -700,7 +700,12 @@ fn do_normalize_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
predicates: Vec<ty::Predicate<'tcx>>)
-> Result<Vec<ty::Predicate<'tcx>>, ErrorReported>
{
debug!("do_normalize_predicates({:?})", predicates);
debug!(
"do_normalize_predicates(predicates={:?}, region_context={:?}, cause={:?})",
predicates,
region_context,
cause,
);
let span = cause.span;
tcx.infer_ctxt().enter(|infcx| {
// FIXME. We should really... do something with these region
Expand Down
11 changes: 11 additions & 0 deletions src/librustc_typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1608,10 +1608,21 @@ fn predicates_defined_on<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
def_id: DefId,
) -> Lrc<ty::GenericPredicates<'tcx>> {
debug!("predicates_defined_on({:?})", def_id);
let mut result = tcx.explicit_predicates_of(def_id);
debug!(
"predicates_defined_on: explicit_predicates_of({:?}) = {:?}",
def_id,
result,
);
let inferred_outlives = tcx.inferred_outlives_of(def_id);
if !inferred_outlives.is_empty() {
let span = tcx.def_span(def_id);
debug!(
"predicates_defined_on: inferred_outlives_of({:?}) = {:?}",
def_id,
inferred_outlives,
);
Lrc::make_mut(&mut result)
.predicates
.extend(inferred_outlives.iter().map(|&p| (p, span)));
Expand Down
38 changes: 29 additions & 9 deletions src/librustc_typeck/outlives/implicit_infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use rustc::hir::def_id::DefId;
use rustc::hir::itemlikevisit::ItemLikeVisitor;
use rustc::ty::subst::{Kind, Subst, UnpackedKind};
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::fold::TypeFoldable;
use rustc::util::nodemap::FxHashMap;

use super::explicit::ExplicitPredicatesMap;
Expand Down Expand Up @@ -245,6 +246,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
}
}

#[derive(Debug)]
pub struct IgnoreSelfTy(bool);

/// We also have to check the explicit predicates
Expand All @@ -270,10 +272,18 @@ pub fn check_explicit_predicates<'tcx>(
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
ignore_self_ty: IgnoreSelfTy,
) {
debug!("def_id = {:?}", &def_id);
debug!("substs = {:?}", &substs);
debug!("explicit_map = {:?}", explicit_map);
debug!("required_predicates = {:?}", required_predicates);
debug!(
"check_explicit_predicates(def_id={:?}, \
substs={:?}, \
explicit_map={:?}, \
required_predicates={:?}, \
ignore_self_ty={:?})",
def_id,
substs,
explicit_map,
required_predicates,
ignore_self_ty,
);
let explicit_predicates = explicit_map.explicit_predicates_of(tcx, *def_id);

for outlives_predicate in explicit_predicates.iter() {
Expand Down Expand Up @@ -302,13 +312,23 @@ pub fn check_explicit_predicates<'tcx>(
//
// Note that we do this check for self **before** applying `substs`. In the
// case that `substs` come from a `dyn Trait` type, our caller will have
// included `Self = dyn Trait<'x, X>` as the value for `Self`. If we were
// included `Self = usize` as the value for `Self`. If we were
// to apply the substs, and not filter this predicate, we might then falsely
// conclude that e.g. `X: 'x` was a reasonable inferred requirement.
if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() {
if ty.is_self() && ignore_self_ty.0 {
debug!("skipping self ty = {:?}", &ty);
continue;
//
// Another similar case is where we have a inferred
// requirement like `<Self as Trait>::Foo: 'b`. We presently
// ignore such requirements as well (cc #54467)-- though
// conceivably it might be better if we could extract the `Foo
// = X` binding from the object type (there must be such a
// binding) and thus infer an outlives requirement that `X:
// 'b`.
if ignore_self_ty.0 {
if let UnpackedKind::Type(ty) = outlives_predicate.0.unpack() {
if ty.has_self_ty() {
debug!("skipping self ty = {:?}", &ty);
continue;
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/librustc_typeck/outlives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ fn inferred_outlives_of<'a, 'tcx>(
}
err.emit();
}

debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);

predicates
}

Expand Down
17 changes: 17 additions & 0 deletions src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Regression test for #54467:
//
// Here, the trait object has an "inferred outlives" requirement that
// `<Self as MyIterator<'a>>::Item: 'a`; but since we don't know what
// `Self` is, we were (incorrectly) messing things up, leading to
// strange errors. This test ensures that we do not give compilation
// errors.
//
// compile-pass

trait MyIterator<'a>: Iterator where Self::Item: 'a { }

struct MyStruct<'a, A> {
item: Box<dyn MyIterator<'a, Item = A>>
}

fn main() { }