From: Niko Matsakis Date: Fri, 10 Mar 2017 02:29:22 +0000 (-0500) Subject: remove type variable defaults code X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=4a0a0e949a077a6d83ca152daa404ff47c9c1dcf;p=rust.git remove type variable defaults code This just limits ourselves to the "old school" defaults: diverging variables and integer variables. --- diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index c995b7e9284..d300552af2c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,7 +88,7 @@ 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}; @@ -105,7 +105,7 @@ 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; @@ -1978,218 +1978,13 @@ fn default_type_parameters(&self) { } } + // 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, _> = - 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>, - default_map: &'b FxHashMap, type_variable::Default<'tcx>>, - conflict: Option>, - ) -> impl Iterator, 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"); diff --git a/src/test/compile-fail/default_ty_param_conflict.rs b/src/test/compile-fail/default_ty_param_conflict.rs deleted file mode 100644 index 8cde239ca6e..00000000000 --- a/src/test/compile-fail/default_ty_param_conflict.rs +++ /dev/null @@ -1,33 +0,0 @@ -// 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 or the MIT license -// , 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 { F::default() } -//~^ NOTE: a default was defined here... - -fn bar(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 -} diff --git a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs b/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs deleted file mode 100644 index e5b035e50aa..00000000000 --- a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs +++ /dev/null @@ -1,32 +0,0 @@ -// 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 or the MIT license -// , 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: Foo) {} -//~^ 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 -} diff --git a/src/test/run-pass/default_ty_param_default_dependent_associated_type.rs b/src/test/run-pass/default_ty_param_default_dependent_associated_type.rs deleted file mode 100644 index 8fc2c2e6bce..00000000000 --- a/src/test/run-pass/default_ty_param_default_dependent_associated_type.rs +++ /dev/null @@ -1,36 +0,0 @@ -// 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 or the MIT license -// , 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 Id for A { - type This = A; -} - -struct Foo::This> { - data: PhantomData<(X, Y)> -} - -impl Foo { - fn new() -> Foo { - Foo { data: PhantomData } - } -} - -fn main() { - let foo = Foo::new(); -} diff --git a/src/test/run-pass/default_ty_param_dependent_defaults.rs b/src/test/run-pass/default_ty_param_dependent_defaults.rs deleted file mode 100644 index ac833d0f547..00000000000 --- a/src/test/run-pass/default_ty_param_dependent_defaults.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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 or the MIT license -// , 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: T, data: PhantomData } - -fn main() { - let foo = Foo { t: 'a', data: PhantomData }; -} diff --git a/src/test/run-pass/default_ty_param_method_call_test.rs b/src/test/run-pass/default_ty_param_method_call_test.rs deleted file mode 100644 index e8d93092ec5..00000000000 --- a/src/test/run-pass/default_ty_param_method_call_test.rs +++ /dev/null @@ -1,24 +0,0 @@ -// 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 or the MIT license -// , 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(&self) -> A { - A::default() - } -} - -fn main() { - let f = Foo.method(); - println!("{}", f); -} diff --git a/src/test/run-pass/default_ty_param_struct.rs b/src/test/run-pass/default_ty_param_struct.rs deleted file mode 100644 index d9ac51fc23b..00000000000 --- a/src/test/run-pass/default_ty_param_struct.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 or the MIT license -// , 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); - -impl Foo { - fn new() -> Foo { - Foo(A::default()) - } -} - -fn main() { - let foo = Foo::new(); -} diff --git a/src/test/run-pass/default_ty_param_struct_and_type_alias.rs b/src/test/run-pass/default_ty_param_struct_and_type_alias.rs deleted file mode 100644 index d3bdab9082e..00000000000 --- a/src/test/run-pass/default_ty_param_struct_and_type_alias.rs +++ /dev/null @@ -1,40 +0,0 @@ -// 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 or the MIT license -// , 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 { - data: PhantomData<(K, V, H)> -} - -impl MyHashMap { - fn new() -> MyHashMap { - MyHashMap { data: PhantomData } - } -} - -mod mystd { - use super::{MyHashMap, RandomHasher}; - pub type HashMap = MyHashMap; -} - -fn try_me(hash_map: mystd::HashMap) {} - -fn main() { - let hash_map = mystd::HashMap::new(); - try_me(hash_map); -} diff --git a/src/test/run-pass/default_ty_param_trait_impl.rs b/src/test/run-pass/default_ty_param_trait_impl.rs deleted file mode 100644 index c67d3a49aff..00000000000 --- a/src/test/run-pass/default_ty_param_trait_impl.rs +++ /dev/null @@ -1,25 +0,0 @@ -// 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 or the MIT license -// , 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 Foo for Vec {} -impl Bar for usize {} - -fn takes_foo(f: F) {} - -fn main() { - let x = Vec::new(); // x: Vec<$0> - takes_foo(x); // adds oblig Vec<$0> : Foo -} diff --git a/src/test/run-pass/default_ty_param_trait_impl_simple.rs b/src/test/run-pass/default_ty_param_trait_impl_simple.rs deleted file mode 100644 index 067ad524922..00000000000 --- a/src/test/run-pass/default_ty_param_trait_impl_simple.rs +++ /dev/null @@ -1,26 +0,0 @@ -// 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 or the MIT license -// , 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 Foo for Vec { - 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 -} diff --git a/src/test/run-pass/default_ty_param_type_alias.rs b/src/test/run-pass/default_ty_param_type_alias.rs deleted file mode 100644 index 1b4747406d0..00000000000 --- a/src/test/run-pass/default_ty_param_type_alias.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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 or the MIT license -// , 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 = HashMap; - -fn main() { - let x = IntMap::new(); -}