use hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_back::slice::ref_slice;
use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin};
-use rustc::infer::type_variable::{self, TypeVariableOrigin};
+use rustc::infer::type_variable::{TypeVariableOrigin};
use rustc::ty::subst::{Kind, Subst, Substs};
use rustc::traits::{self, ObligationCause, ObligationCauseCode, Reveal};
use rustc::ty::{ParamTy, ParameterEnvironment};
use TypeAndSubsts;
use lint;
use util::common::{ErrorReported, indenter};
-use util::nodemap::{DefIdMap, FxHashMap, FxHashSet, NodeMap};
+use util::nodemap::{DefIdMap, FxHashMap, NodeMap};
use std::cell::{Cell, RefCell};
use std::cmp;
}
}
+ // Implements type inference fallback algorithm
fn select_all_obligations_and_apply_defaults(&self) {
- if self.tcx.sess.features.borrow().default_type_parameter_fallback {
- self.new_select_all_obligations_and_apply_defaults();
- } else {
- self.old_select_all_obligations_and_apply_defaults();
- }
- }
-
- // Implements old type inference fallback algorithm
- fn old_select_all_obligations_and_apply_defaults(&self) {
self.select_obligations_where_possible();
self.default_type_parameters();
self.select_obligations_where_possible();
}
- fn new_select_all_obligations_and_apply_defaults(&self) {
- use rustc::ty::error::UnconstrainedNumeric::Neither;
- use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
-
- // For the time being this errs on the side of being memory wasteful but provides better
- // error reporting.
- // let type_variables = self.type_variables.clone();
-
- // There is a possibility that this algorithm will have to run an arbitrary number of times
- // to terminate so we bound it by the compiler's recursion limit.
- for _ in 0..self.tcx.sess.recursion_limit.get() {
- // First we try to solve all obligations, it is possible that the last iteration
- // has made it possible to make more progress.
- self.select_obligations_where_possible();
-
- let mut conflicts = Vec::new();
-
- // Collect all unsolved type, integral and floating point variables.
- let unsolved_variables = self.unsolved_variables();
-
- // We must collect the defaults *before* we do any unification. Because we have
- // directly attached defaults to the type variables any unification that occurs
- // will erase defaults causing conflicting defaults to be completely ignored.
- let default_map: FxHashMap<Ty<'tcx>, _> =
- unsolved_variables
- .iter()
- .filter_map(|t| self.default(t).map(|d| (*t, d)))
- .collect();
-
- let mut unbound_tyvars = FxHashSet();
-
- debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map);
-
- // We loop over the unsolved variables, resolving them and if they are
- // and unconstrainted numeric type we add them to the set of unbound
- // variables. We do this so we only apply literal fallback to type
- // variables without defaults.
- for ty in &unsolved_variables {
- let resolved = self.resolve_type_vars_if_possible(ty);
- if self.type_var_diverges(resolved) {
- self.demand_eqtype(syntax_pos::DUMMY_SP, *ty,
- self.tcx.mk_diverging_default());
- } else {
- match self.type_is_unconstrained_numeric(resolved) {
- UnconstrainedInt | UnconstrainedFloat => {
- unbound_tyvars.insert(resolved);
- },
- Neither => {}
- }
- }
- }
-
- // We now remove any numeric types that also have defaults, and instead insert
- // the type variable with a defined fallback.
- for ty in &unsolved_variables {
- if let Some(_default) = default_map.get(ty) {
- let resolved = self.resolve_type_vars_if_possible(ty);
-
- debug!("select_all_obligations_and_apply_defaults: \
- ty: {:?} with default: {:?}",
- ty, _default);
-
- match resolved.sty {
- ty::TyInfer(ty::TyVar(_)) => {
- unbound_tyvars.insert(ty);
- }
-
- ty::TyInfer(ty::IntVar(_)) | ty::TyInfer(ty::FloatVar(_)) => {
- unbound_tyvars.insert(ty);
- if unbound_tyvars.contains(resolved) {
- unbound_tyvars.remove(resolved);
- }
- }
-
- _ => {}
- }
- }
- }
-
- // If there are no more fallbacks to apply at this point we have applied all possible
- // defaults and type inference will proceed as normal.
- if unbound_tyvars.is_empty() {
- break;
- }
-
- // Finally we go through each of the unbound type variables and unify them with
- // the proper fallback, reporting a conflicting default error if any of the
- // unifications fail. We know it must be a conflicting default because the
- // variable would only be in `unbound_tyvars` and have a concrete value if
- // it had been solved by previously applying a default.
-
- // We wrap this in a transaction for error reporting, if we detect a conflict
- // we will rollback the inference context to its prior state so we can probe
- // for conflicts and correctly report them.
-
- let _ = self.commit_if_ok(|_: &infer::CombinedSnapshot| {
- conflicts.extend(
- self.apply_defaults_and_return_conflicts(&unbound_tyvars, &default_map, None)
- );
-
- // If there are conflicts we rollback, otherwise commit
- if conflicts.len() > 0 {
- Err(())
- } else {
- Ok(())
- }
- });
-
- // Loop through each conflicting default, figuring out the default that caused
- // a unification failure and then report an error for each.
- for (conflict, default) in conflicts {
- let conflicting_default =
- self.apply_defaults_and_return_conflicts(
- &unbound_tyvars,
- &default_map,
- Some(conflict)
- )
- .last()
- .map(|(_, tv)| tv)
- .unwrap_or(type_variable::Default {
- ty: self.next_ty_var(
- TypeVariableOrigin::MiscVariable(syntax_pos::DUMMY_SP)),
- origin_span: syntax_pos::DUMMY_SP,
- // what do I put here?
- def_id: self.tcx.hir.local_def_id(ast::CRATE_NODE_ID)
- });
-
- // This is to ensure that we elimnate any non-determinism from the error
- // reporting by fixing an order, it doesn't matter what order we choose
- // just that it is consistent.
- let (first_default, second_default) =
- if default.def_id < conflicting_default.def_id {
- (default, conflicting_default)
- } else {
- (conflicting_default, default)
- };
-
-
- self.report_conflicting_default_types(
- first_default.origin_span,
- self.body_id,
- first_default,
- second_default)
- }
- }
-
- self.select_obligations_where_possible();
- }
-
- // For use in error handling related to default type parameter fallback. We explicitly
- // apply the default that caused conflict first to a local version of the type variable
- // table then apply defaults until we find a conflict. That default must be the one
- // that caused conflict earlier.
- fn apply_defaults_and_return_conflicts<'b>(
- &'b self,
- unbound_vars: &'b FxHashSet<Ty<'tcx>>,
- default_map: &'b FxHashMap<Ty<'tcx>, type_variable::Default<'tcx>>,
- conflict: Option<Ty<'tcx>>,
- ) -> impl Iterator<Item=(Ty<'tcx>, type_variable::Default<'tcx>)> + 'b {
- use rustc::ty::error::UnconstrainedNumeric::Neither;
- use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat};
-
- conflict.into_iter().chain(unbound_vars.iter().cloned()).flat_map(move |ty| {
- if self.type_var_diverges(ty) {
- self.demand_eqtype(syntax_pos::DUMMY_SP, ty,
- self.tcx.mk_diverging_default());
- } else {
- match self.type_is_unconstrained_numeric(ty) {
- UnconstrainedInt => {
- self.demand_eqtype(syntax_pos::DUMMY_SP, ty, self.tcx.types.i32)
- },
- UnconstrainedFloat => {
- self.demand_eqtype(syntax_pos::DUMMY_SP, ty, self.tcx.types.f64)
- },
- Neither => {
- if let Some(default) = default_map.get(ty) {
- let default = default.clone();
- let default_ty = self.normalize_associated_types_in(
- default.origin_span, &default.ty);
- match self.eq_types(false,
- &self.misc(default.origin_span),
- ty,
- default_ty) {
- Ok(ok) => self.register_infer_ok_obligations(ok),
- Err(_) => {
- return Some((ty, default));
- }
- }
- }
- }
- }
- }
-
- None
- })
- }
-
fn select_all_obligations_or_error(&self) {
debug!("select_all_obligations_or_error");
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-use std::fmt::Debug;
-
-// Example from the RFC
-fn foo<F:Default=usize>() -> F { F::default() }
-//~^ NOTE: a default was defined here...
-
-fn bar<B:Debug=isize>(b: B) { println!("{:?}", b); }
-//~^ NOTE: a second default was defined here...
-
-fn main() {
- // Here, F is instantiated with $0=uint
- let x = foo();
- //~^ ERROR: mismatched types
- //~| NOTE: conflicting type parameter defaults `usize` and `isize`
- //~| NOTE: conflicting type parameter defaults `usize` and `isize`
- //~| NOTE: ...that was applied to an unconstrained type variable here
-
- // Here, B is instantiated with $1=uint, and constraint $0 <: $1 is added.
- bar(x);
- //~^ NOTE: ...that also applies to the same type variable here
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-//aux-build:default_ty_param_cross_crate_crate.rs
-
-#![feature(default_type_parameter_fallback)]
-
-extern crate default_param_test;
-
-use default_param_test::{Foo, bleh};
-
-fn meh<X, B=bool>(x: Foo<X, B>) {}
-//~^ NOTE: a default was defined here...
-
-fn main() {
- let foo = bleh();
- //~^ NOTE: ...that also applies to the same type variable here
-
- meh(foo);
- //~^ ERROR: mismatched types
- //~| NOTE: conflicting type parameter defaults `bool` and `char`
- //~| NOTE: conflicting type parameter defaults `bool` and `char`
- //~| a second default is defined on `default_param_test::bleh`
- //~| NOTE: ...that was applied to an unconstrained type variable here
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-
-#![feature(default_type_parameter_fallback)]
-
-use std::marker::PhantomData;
-
-trait Id {
- type This;
-}
-
-impl<A> Id for A {
- type This = A;
-}
-
-struct Foo<X: Default = usize, Y = <X as Id>::This> {
- data: PhantomData<(X, Y)>
-}
-
-impl<X: Default, Y> Foo<X, Y> {
- fn new() -> Foo<X, Y> {
- Foo { data: PhantomData }
- }
-}
-
-fn main() {
- let foo = Foo::new();
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-
-#![feature(default_type_parameter_fallback)]
-use std::marker::PhantomData;
-
-struct Foo<T,U=T> { t: T, data: PhantomData<U> }
-
-fn main() {
- let foo = Foo { t: 'a', data: PhantomData };
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-struct Foo;
-
-impl Foo {
- fn method<A:Default=String>(&self) -> A {
- A::default()
- }
-}
-
-fn main() {
- let f = Foo.method();
- println!("{}", f);
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-struct Foo<A>(A);
-
-impl<A:Default=i32> Foo<A> {
- fn new() -> Foo<A> {
- Foo(A::default())
- }
-}
-
-fn main() {
- let foo = Foo::new();
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-//
-
-#![feature(default_type_parameter_fallback)]
-
-use std::marker::PhantomData;
-
-pub struct DeterministicHasher;
-pub struct RandomHasher;
-
-
-pub struct MyHashMap<K, V, H=DeterministicHasher> {
- data: PhantomData<(K, V, H)>
-}
-
-impl<K, V, H> MyHashMap<K, V, H> {
- fn new() -> MyHashMap<K, V, H> {
- MyHashMap { data: PhantomData }
- }
-}
-
-mod mystd {
- use super::{MyHashMap, RandomHasher};
- pub type HashMap<K, V, H=RandomHasher> = MyHashMap<K, V, H>;
-}
-
-fn try_me<H>(hash_map: mystd::HashMap<i32, i32, H>) {}
-
-fn main() {
- let hash_map = mystd::HashMap::new();
- try_me(hash_map);
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-// Another example from the RFC
-trait Foo { }
-trait Bar { }
-
-impl<T:Bar=usize> Foo for Vec<T> {}
-impl Bar for usize {}
-
-fn takes_foo<F:Foo>(f: F) {}
-
-fn main() {
- let x = Vec::new(); // x: Vec<$0>
- takes_foo(x); // adds oblig Vec<$0> : Foo
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-// An example from the RFC
-trait Foo { fn takes_foo(&self); }
-trait Bar { }
-
-impl<T:Bar=usize> Foo for Vec<T> {
- fn takes_foo(&self) {}
-}
-
-impl Bar for usize {}
-
-fn main() {
- let x = Vec::new(); // x: Vec<$0>
- x.takes_foo(); // adds oblig Vec<$0> : Foo
-}
+++ /dev/null
-// Copyright 2015 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(default_type_parameter_fallback)]
-
-use std::collections::HashMap;
-
-type IntMap<K=usize> = HashMap<K, usize>;
-
-fn main() {
- let x = IntMap::new();
-}