Skip to content

Commit

Permalink
Auto merge of #27866 - arielb1:really-fast-reject, r=nikomatsakis
Browse files Browse the repository at this point in the history
also, use the right caching logic for type_moves_by_default (this was
broken by @jroesch).

```
before:
593.10user 5.21system 7:51.41elapsed 126%CPU (0avgtext+0avgdata 1150016maxresident)k

after:
567.03user 4.00system 7:28.23elapsed 127%CPU (0avgtext+0avgdata 1133112maxresident)k
```

A nice 4.5% improvement. For reference, on the last run LLVM takes 429.267s, which is 75% - hopefully this can be reduced.

I think the regression since #27751 is because of the wf patch - need to investigate it through.

r? @nikomatsakis
  • Loading branch information
bors committed Aug 18, 2015
2 parents 4c0ffc0 + 13809ff commit 16cacbe
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 24 deletions.
10 changes: 6 additions & 4 deletions src/librustc/middle/fast_reject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,13 @@ pub fn simplify_type(tcx: &ty::ctxt,
ty::TyBareFn(_, ref f) => {
Some(FunctionSimplifiedType(f.sig.0.inputs.len()))
}
ty::TyProjection(_) => {
None
}
ty::TyParam(_) => {
ty::TyProjection(_) | ty::TyParam(_) => {
if can_simplify_params {
// In normalized types, projections don't unify with
// anything. when lazy normalization happens, this
// will change. It would still be nice to have a way
// to deal with known-not-to-unify-with-anything
// projections (e.g. the likes of <__S as Encoder>::Error).
Some(ParameterSimplifiedType)
} else {
None
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/infer/higher_ranked/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
snapshot: &CombinedSnapshot,
value: &T)
-> T
where T : TypeFoldable<'tcx>
where T : TypeFoldable<'tcx> + ty::HasTypeFlags
{
debug_assert!(leak_check(infcx, &skol_map, snapshot).is_ok());

Expand Down
21 changes: 16 additions & 5 deletions src/librustc/middle/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -985,7 +985,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
snapshot: &CombinedSnapshot,
value: &T)
-> T
where T : TypeFoldable<'tcx>
where T : TypeFoldable<'tcx> + HasTypeFlags
{
/*! See `higher_ranked::plug_leaks` */

Expand Down Expand Up @@ -1256,7 +1256,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
}

pub fn resolve_type_vars_if_possible<T:TypeFoldable<'tcx>>(&self, value: &T) -> T {
pub fn resolve_type_vars_if_possible<T>(&self, value: &T) -> T
where T: TypeFoldable<'tcx> + HasTypeFlags
{
/*!
* Where possible, replaces type/int/float variables in
* `value` with their final value. Note that region variables
Expand All @@ -1266,6 +1268,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
* at will.
*/

if !value.needs_infer() {
return value.clone(); // avoid duplicated subst-folding
}
let mut r = resolve::OpportunisticTypeResolver::new(self);
value.fold_with(&mut r)
}
Expand Down Expand Up @@ -1456,9 +1461,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {

pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
let ty = self.resolve_type_vars_if_possible(&ty);
!traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
// FIXME(@jroesch): should be able to use:
// ty.moves_by_default(&self.parameter_environment, span)
if ty.needs_infer() {
// this can get called from typeck (by euv), and moves_by_default
// rightly refuses to work with inference variables, but
// moves_by_default has a cache, which we want to use in other
// cases.
!traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundCopy, span)
} else {
ty.moves_by_default(&self.parameter_environment, span)
}
}

pub fn node_method_ty(&self, method_call: ty::MethodCall)
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
obligation: &Obligation<'tcx, T>)
-> !
where T: fmt::Display + TypeFoldable<'tcx>
where T: fmt::Display + TypeFoldable<'tcx> + HasTypeFlags
{
let predicate =
infcx.resolve_type_vars_if_possible(&obligation.predicate);
Expand Down
7 changes: 3 additions & 4 deletions src/librustc/middle/traits/fulfill.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ use middle::infer::InferCtxt;
use middle::ty::{self, RegionEscape, Ty, HasTypeFlags};
use middle::wf;

use std::collections::HashSet;
use std::fmt;
use syntax::ast;
use util::common::ErrorReported;
use util::nodemap::NodeMap;
use util::nodemap::{FnvHashSet, NodeMap};

use super::CodeAmbiguity;
use super::CodeProjectionError;
Expand All @@ -33,7 +32,7 @@ use super::Unimplemented;
use super::util::predicate_for_builtin_bound;

pub struct FulfilledPredicates<'tcx> {
set: HashSet<(RFC1214Warning, ty::Predicate<'tcx>)>
set: FnvHashSet<(RFC1214Warning, ty::Predicate<'tcx>)>
}

/// The fulfillment context is used to drive trait resolution. It
Expand Down Expand Up @@ -540,7 +539,7 @@ fn register_region_obligation<'tcx>(t_a: Ty<'tcx>,
impl<'tcx> FulfilledPredicates<'tcx> {
pub fn new() -> FulfilledPredicates<'tcx> {
FulfilledPredicates {
set: HashSet::new()
set: FnvHashSet()
}
}

Expand Down
7 changes: 7 additions & 0 deletions src/librustc/middle/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -927,6 +927,13 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Normalized<'tcx, T> {
}
}

impl<'tcx, T: HasTypeFlags> HasTypeFlags for Normalized<'tcx, T> {
fn has_type_flags(&self, flags: ty::TypeFlags) -> bool {
self.value.has_type_flags(flags) ||
self.obligations.has_type_flags(flags)
}
}

impl<'tcx, T:fmt::Debug> fmt::Debug for Normalized<'tcx, T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Normalized({:?},{:?})",
Expand Down
57 changes: 50 additions & 7 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3192,6 +3192,8 @@ impl<'tcx> TraitDef<'tcx> {
}
}

/// Iterate over every impl that could possibly match the
/// self-type `self_ty`.
pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
tcx: &ctxt<'tcx>,
self_ty: Ty<'tcx>,
Expand All @@ -3203,18 +3205,29 @@ impl<'tcx> TraitDef<'tcx> {
f(impl_def_id);
}

if let Some(simp) = fast_reject::simplify_type(tcx, self_ty, false) {
// simplify_type(.., false) basically replaces type parameters and
// projections with infer-variables. This is, of course, done on
// the impl trait-ref when it is instantiated, but not on the
// predicate trait-ref which is passed here.
//
// for example, if we match `S: Copy` against an impl like
// `impl<T:Copy> Copy for Option<T>`, we replace the type variable
// in `Option<T>` with an infer variable, to `Option<_>` (this
// doesn't actually change fast_reject output), but we don't
// replace `S` with anything - this impl of course can't be
// selected, and as there are hundreds of similar impls,
// considering them would significantly harm performance.
if let Some(simp) = fast_reject::simplify_type(tcx, self_ty, true) {
if let Some(impls) = self.nonblanket_impls.borrow().get(&simp) {
for &impl_def_id in impls {
f(impl_def_id);
}
return; // we don't need to process the other non-blanket impls
}
}

for v in self.nonblanket_impls.borrow().values() {
for &impl_def_id in v {
f(impl_def_id);
} else {
for v in self.nonblanket_impls.borrow().values() {
for &impl_def_id in v {
f(impl_def_id);
}
}
}
}
Expand Down Expand Up @@ -7267,6 +7280,24 @@ impl<'tcx,T:HasTypeFlags> HasTypeFlags for VecPerParamSpace<T> {
}
}

impl HasTypeFlags for abi::Abi {
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
false
}
}

impl HasTypeFlags for ast::Unsafety {
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
false
}
}

impl HasTypeFlags for BuiltinBounds {
fn has_type_flags(&self, _flags: TypeFlags) -> bool {
false
}
}

impl<'tcx> HasTypeFlags for ClosureTy<'tcx> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.sig.has_type_flags(flags)
Expand All @@ -7279,6 +7310,12 @@ impl<'tcx> HasTypeFlags for ClosureUpvar<'tcx> {
}
}

impl<'tcx> HasTypeFlags for ExistentialBounds<'tcx> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.projection_bounds.has_type_flags(flags)
}
}

impl<'tcx> HasTypeFlags for ty::InstantiatedPredicates<'tcx> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.predicates.has_type_flags(flags)
Expand Down Expand Up @@ -7354,6 +7391,12 @@ impl<'tcx> HasTypeFlags for Ty<'tcx> {
}
}

impl<'tcx> HasTypeFlags for TypeAndMut<'tcx> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.ty.has_type_flags(flags)
}
}

impl<'tcx> HasTypeFlags for TraitRef<'tcx> {
fn has_type_flags(&self, flags: TypeFlags) -> bool {
self.substs.has_type_flags(flags)
Expand Down
4 changes: 2 additions & 2 deletions src/librustc/middle/ty_relate/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
//! type equality, etc.

use middle::subst::{ErasedRegions, NonerasedRegions, ParamSpace, Substs};
use middle::ty::{self, Ty, TypeError};
use middle::ty::{self, HasTypeFlags, Ty, TypeError};
use middle::ty_fold::TypeFoldable;
use std::rc::Rc;
use syntax::abi;
Expand Down Expand Up @@ -78,7 +78,7 @@ pub trait TypeRelation<'a,'tcx> : Sized {
where T: Relate<'a,'tcx>;
}

pub trait Relate<'a,'tcx>: TypeFoldable<'tcx> {
pub trait Relate<'a,'tcx>: TypeFoldable<'tcx> + HasTypeFlags {
fn relate<R:TypeRelation<'a,'tcx>>(relation: &mut R,
a: &Self,
b: &Self)
Expand Down

0 comments on commit 16cacbe

Please sign in to comment.