Auto merge of #56003 - nikomatsakis:issue-54467-infer-outlives-bounds-and-trait-objects, r=eddyb
do not propagate inferred bounds on trait objects if they involve `Self` Fixes #54467, which is a Rust 2018 Release blocking issue. r? @eddyb
This commit is contained in:
commit
f37247f885
@ -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
|
||||
|
@ -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)));
|
||||
|
@ -14,6 +14,7 @@
|
||||
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;
|
||||
@ -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
|
||||
@ -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() {
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,9 @@ fn inferred_outlives_of<'a, 'tcx>(
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
|
||||
debug!("inferred_outlives_of({:?}) = {:?}", item_def_id, predicates);
|
||||
|
||||
predicates
|
||||
}
|
||||
|
||||
|
17
src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
Normal file
17
src/test/ui/rfc-2093-infer-outlives/issue-54467.rs
Normal file
@ -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() { }
|
Loading…
Reference in New Issue
Block a user