diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index cddd59fa83c1b..1434b0e60e21c 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -107,6 +107,11 @@ impl FlagComputation { } &ty::TyProjection(ref data) => { + // currently we can't normalize projections that + // include bound regions, so track those separately. + if !data.has_escaping_regions() { + self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION); + } self.add_flags(TypeFlags::HAS_PROJECTION); self.add_projection_ty(data); } diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index 2c18d1d52547f..886ad8cd8611d 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -105,7 +105,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { TypeFlags::HAS_FREE_REGIONS | TypeFlags::HAS_TY_INFER | TypeFlags::HAS_PARAMS | - TypeFlags::HAS_PROJECTION | + TypeFlags::HAS_NORMALIZABLE_PROJECTION | TypeFlags::HAS_TY_ERR | TypeFlags::HAS_SELF) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 717b8923a1635..723af1f0d90a4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -462,6 +462,10 @@ bitflags! { // Only set for TyInfer other than Fresh. const KEEP_IN_LOCAL_TCX = 1 << 11, + // Is there a projection that does not involve a bound region? + // Currently we can't normalize projections w/ bound regions. + const HAS_NORMALIZABLE_PROJECTION = 1 << 12, + const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | TypeFlags::HAS_SELF.bits | TypeFlags::HAS_RE_EARLY_BOUND.bits, diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 429bc7490fc7b..8112bb8e65c5b 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -1019,7 +1019,9 @@ fn create_fn_trans_item<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, let concrete_substs = monomorphize::apply_param_substs(scx, param_substs, &fn_substs); - assert!(concrete_substs.is_normalized_for_trans()); + assert!(concrete_substs.is_normalized_for_trans(), + "concrete_substs not normalized for trans: {:?}", + concrete_substs); TransItem::Fn(Instance::new(def_id, concrete_substs)) } diff --git a/src/test/run-pass/issue-36381.rs b/src/test/run-pass/issue-36381.rs new file mode 100644 index 0000000000000..6cd991bd942df --- /dev/null +++ b/src/test/run-pass/issue-36381.rs @@ -0,0 +1,34 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Regression test for #36381. The trans collector was asserting that +// there are no projection types, but the `<&str as +// StreamOnce>::Position` projection contained a late-bound region, +// and we don't currently normalize in that case until the function is +// actually invoked. + +pub trait StreamOnce { + type Position; +} + +impl<'a> StreamOnce for &'a str { + type Position = usize; +} + +pub fn parser(_: F) { +} + +fn follow(_: &str) -> <&str as StreamOnce>::Position { + panic!() +} + +fn main() { + parser(follow); +}