diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 917727907ba88..d193975d35f48 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -616,40 +616,52 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// Returns a type variable's default fallback if any exists. A default /// must be attached to the variable when created, if it is created - /// without a default, this will return None. + /// without a default, this will return NoDefault. /// /// This code does not apply to integral or floating point variables, /// only to use declared defaults. /// /// See `new_ty_var_with_default` to create a type variable with a default. /// See `type_variable::Default` for details about what a default entails. - pub fn default(&self, ty: Ty<'tcx>) -> Option> { + pub fn default(&self, ty: Ty<'tcx>) -> type_variable::Default<'tcx> { match ty.sty { - ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid), - _ => None + ty::TyInfer(ty::TyVar(vid)) => self.type_variables + .borrow() + .default(vid) + .clone(), + _ => type_variable::Default::None, } } - pub fn unsolved_variables(&self) -> Vec> { + // Returns a vector containing all type variables that have an applicable default, + // along with their defaults. + // + // NB: You must be careful to only apply defaults once, if a variable is unififed + // it many no longer be unsolved and apply a second default will mostly likely + // result in a type error. + pub fn candidates_for_defaulting(&self) + -> Vec<(ty::Ty<'tcx>, type_variable::Default<'tcx>)> { let mut variables = Vec::new(); let unbound_ty_vars = self.type_variables .borrow() - .unsolved_variables() + .candidates_for_defaulting() .into_iter() - .map(|t| self.tcx.mk_var(t)); + .map(|(t, d)| (self.tcx.mk_var(t), d)); let unbound_int_vars = self.int_unification_table .borrow_mut() .unsolved_variables() .into_iter() - .map(|v| self.tcx.mk_int_var(v)); + .map(|v| (self.tcx.mk_int_var(v), + type_variable::Default::Integer)); let unbound_float_vars = self.float_unification_table .borrow_mut() .unsolved_variables() .into_iter() - .map(|v| self.tcx.mk_float_var(v)); + .map(|v| (self.tcx.mk_float_var(v), + type_variable::Default::Float)); variables.extend(unbound_ty_vars); variables.extend(unbound_int_vars); @@ -960,7 +972,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } pub fn next_ty_var_with_default(&self, - default: Option>) -> Ty<'tcx> { + default: Option>) -> Ty<'tcx> { let ty_var_id = self.type_variables .borrow_mut() .new_var(false, default); @@ -1013,7 +1025,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { for def in defs.iter() { let default = def.default.map(|default| { - type_variable::Default { + type_variable::UserDefault { ty: default.subst_spanned(self.tcx, substs, Some(span)), origin_span: span, def_id: def.default_def_id @@ -1319,13 +1331,13 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { pub fn report_conflicting_default_types(&self, span: Span, - expected: type_variable::Default<'tcx>, - actual: type_variable::Default<'tcx>) { + expected: type_variable::UserDefault<'tcx>, + actual: type_variable::UserDefault<'tcx>) { let trace = TypeTrace { origin: Misc(span), values: Types(ExpectedFound { expected: expected.ty, - found: actual.ty + found: actual.ty, }) }; diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs index e4af098c2a42d..caec364af4813 100644 --- a/src/librustc/middle/infer/type_variable.rs +++ b/src/librustc/middle/infer/type_variable.rs @@ -27,21 +27,30 @@ pub struct TypeVariableTable<'tcx> { struct TypeVariableData<'tcx> { value: TypeVariableValue<'tcx>, - diverging: bool + default: Default<'tcx>, } enum TypeVariableValue<'tcx> { Known(Ty<'tcx>), Bounded { relations: Vec, - default: Option> } } -// We will use this to store the required information to recapitulate what happened when -// an error occurs. #[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Default<'tcx> { +pub enum Default<'tcx> { + User(UserDefault<'tcx>), + Integer, + Float, + Diverging, + None, +} + +// We will use this to store the required information to recapitulate +// what happened when an error occurs. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct UserDefault<'tcx> { + /// The default type provided by the user pub ty: Ty<'tcx>, /// The span where the default was incurred pub origin_span: Span, @@ -53,9 +62,9 @@ pub struct Snapshot { snapshot: sv::Snapshot } -enum UndoEntry<'tcx> { +enum UndoEntry { // The type of the var was specified. - SpecifyVar(ty::TyVid, Vec, Option>), + SpecifyVar(ty::TyVid, Vec), Relate(ty::TyVid, ty::TyVid), } @@ -88,15 +97,15 @@ impl<'tcx> TypeVariableTable<'tcx> { relations(self.values.get_mut(a.index as usize)) } - pub fn default(&self, vid: ty::TyVid) -> Option> { - match &self.values.get(vid.index as usize).value { - &Known(_) => None, - &Bounded { ref default, .. } => default.clone() - } + pub fn default(&self, vid: ty::TyVid) -> &Default<'tcx> { + &self.values.get(vid.index as usize).default } pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool { - self.values.get(vid.index as usize).diverging + match self.values.get(vid.index as usize).default { + Default::Diverging => true, + _ => false, + } } /// Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`. @@ -124,8 +133,8 @@ impl<'tcx> TypeVariableTable<'tcx> { mem::replace(value_ptr, Known(ty)) }; - let (relations, default) = match old_value { - Bounded { relations, default } => (relations, default), + let relations = match old_value { + Bounded { relations } => relations , Known(_) => panic!("Asked to instantiate variable that is \ already instantiated") }; @@ -134,16 +143,24 @@ impl<'tcx> TypeVariableTable<'tcx> { stack.push((ty, dir, vid)); } - self.values.record(SpecifyVar(vid, relations, default)); + self.values.record(SpecifyVar(vid, relations)); } pub fn new_var(&mut self, diverging: bool, - default: Option>) -> ty::TyVid { + default: Option>) -> ty::TyVid { + let default = if diverging { + Default::Diverging + } else { + default.map(|u| Default::User(u)) + .unwrap_or(Default::None) + }; + let index = self.values.push(TypeVariableData { - value: Bounded { relations: vec![], default: default }, - diverging: diverging + value: Bounded { relations: vec![] }, + default: default, }); + ty::TyVid { index: index as u32 } } @@ -204,7 +221,7 @@ impl<'tcx> TypeVariableTable<'tcx> { debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold); } - sv::UndoLog::Other(SpecifyVar(vid, _, _)) => { + sv::UndoLog::Other(SpecifyVar(vid, _)) => { if vid.index < new_elem_threshold { // quick check to see if this variable was // created since the snapshot started or not. @@ -221,28 +238,34 @@ impl<'tcx> TypeVariableTable<'tcx> { escaping_types } - pub fn unsolved_variables(&self) -> Vec { + pub fn candidates_for_defaulting(&self) -> Vec<(ty::TyVid, Default<'tcx>)> { self.values .iter() .enumerate() - .filter_map(|(i, value)| match &value.value { - &TypeVariableValue::Known(_) => None, - &TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 }) - }) - .collect() + .filter_map(|(i, value)| { + let vid = match &value.value { + &TypeVariableValue::Bounded { .. } => Some(ty::TyVid { index: i as u32 }), + &TypeVariableValue::Known(v) => match v.sty { + ty::TyInfer(ty::FloatVar(_)) | ty::TyInfer(ty::IntVar(_)) => + Some(ty::TyVid { index: i as u32 }), + _ => None + } + }; + vid.map(|v| (v, value.default.clone())) + }) + .collect() } } impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> { type Value = TypeVariableData<'tcx>; - type Undo = UndoEntry<'tcx>; + type Undo = UndoEntry; - fn reverse(values: &mut Vec>, action: UndoEntry<'tcx>) { + fn reverse(values: &mut Vec>, action: UndoEntry) { match action { - SpecifyVar(vid, relations, default) => { + SpecifyVar(vid, relations) => { values[vid.index as usize].value = Bounded { relations: relations, - default: default }; } diff --git a/src/librustc/middle/ty/error.rs b/src/librustc/middle/ty/error.rs index 72c4366c5bcd5..a4cbb19055f14 100644 --- a/src/librustc/middle/ty/error.rs +++ b/src/librustc/middle/ty/error.rs @@ -57,7 +57,7 @@ pub enum TypeError<'tcx> { ConvergenceMismatch(ExpectedFound), ProjectionNameMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), - TyParamDefaultMismatch(ExpectedFound>) + TyParamDefaultMismatch(ExpectedFound>) } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 9dd7cfea43f69..9331ca6c48e90 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -88,6 +88,7 @@ use middle::def; use middle::def_id::{DefId, LOCAL_CRATE}; use middle::infer; use middle::infer::type_variable; +use middle::infer::type_variable::Default; use middle::pat_util::{self, pat_id_map}; use middle::privacy::{AllPublic, LastMod}; use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace}; @@ -1186,7 +1187,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { span: Span) -> Ty<'tcx> { // Grab the default doing subsitution let default = ty_param_def.and_then(|def| { - def.default.map(|ty| type_variable::Default { + def.default.map(|ty| type_variable::UserDefault { ty: ty.subst_spanned(self.tcx(), substs.as_ref().unwrap(), Some(span)), origin_span: span, def_id: def.default_def_id @@ -1766,17 +1767,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - /// Apply "fallbacks" to some types - /// ! gets replaced with (), unconstrained ints with i32, and unconstrained floats with f64. fn default_type_parameters(&self) { - use middle::ty::error::UnconstrainedNumeric::Neither; - use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; - for ty in &self.infcx().unsolved_variables() { + use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat, Neither}; + let unsolved_variables = self.infcx().candidates_for_defaulting(); + for &(ref ty, _) in &unsolved_variables { let resolved = self.infcx().resolve_type_vars_if_possible(ty); - if self.infcx().type_var_diverges(resolved) { + let diverges = self.infcx().type_var_diverges(resolved); + if diverges { demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil()); } else { - match self.infcx().type_is_unconstrained_numeric(resolved) { + let unconstrained = + self.infcx().type_is_unconstrained_numeric(resolved); + match unconstrained { UnconstrainedInt => { demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32) }, @@ -1808,11 +1810,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { use middle::ty::error::UnconstrainedNumeric::Neither; use middle::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.infcx().type_variables.clone(); - - // There is a possibility that this algorithm will have to run an arbitrary number of times + // It is a possible 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 @@ -1822,107 +1820,70 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut conflicts = Vec::new(); // Collect all unsolved type, integral and floating point variables. - let unsolved_variables = self.inh.infcx.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: FnvHashMap<_, _> = - unsolved_variables - .iter() - .filter_map(|t| self.infcx().default(t).map(|d| (t, d))) - .collect(); - - let mut unbound_tyvars = HashSet::new(); - - debug!("select_all_obligations_and_apply_defaults: defaults={:?}", default_map); - - // We loop over the unsolved variables, resolving them and if they are - // and unconstrainted numberic 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.infcx().resolve_type_vars_if_possible(ty); - if self.infcx().type_var_diverges(resolved) { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil()); - } else { - match self.infcx().type_is_unconstrained_numeric(resolved) { - UnconstrainedInt | UnconstrainedFloat => { - unbound_tyvars.insert(resolved); - }, - Neither => {} - } - } - } + let defaults_to_apply = self.inh.infcx.candidates_for_defaulting(); - // 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.infcx().resolve_type_vars_if_possible(ty); + let mut has_user_default = HashSet::new(); + let mut has_literal_fallback = HashSet::new(); + let mut is_diverging = HashSet::new(); - debug!("select_all_obligations_and_apply_defaults: ty: {:?} with default: {:?}", - ty, _default); + // Examine all unsolved variables, and narrow them to the set that have applicable + // defaults. We want to process any unsolved variables that have either an explicit + // user default, literal fallback, or are diverging. + for &(ref ty, ref default) in &defaults_to_apply { + // We should NEVER process anything but a TyInfer. + assert!(match ty.sty { ty::TyInfer(_) => true, _ => false }); - 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); - } - } + match default { + &Default::User(ref user_default) => { + debug!("select_all_obligations_and_apply_defaults: \ + ty: {:?} with default: {:?}", ty, default); - _ => {} + has_user_default.insert((*ty, user_default.clone())); + }, + &Default::Float | + &Default::Integer => { + has_literal_fallback.insert(*ty); + } + &Default::Diverging => { + is_diverging.insert(*ty); } + &Default::None => {} } } // If there are no more fallbacks to apply at this point we have applied all possible // defaults and type inference will procede as normal. - if unbound_tyvars.is_empty() { + if has_user_default.len() == 0 && + has_literal_fallback.len() == 0 && + is_diverging.len() == 0 { break; } - // Finally we go through each of the unbound type variables and unify them with + // Finally we loop 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. - + // unifications fail. + // + // We know that a conflict must be due to multiple applicable defaults, because the + // variable would only be in `unbound_tyvars` and have been previously unified with + // another type if we had applied a default. + // We wrap all of this in a transaction for error reporting. If we detect a conflict + // we will rollback to the previous state so we can check what conflicts and + // correctly report them. let _ = self.infcx().commit_if_ok(|_: &infer::CombinedSnapshot| { - for ty in &unbound_tyvars { - if self.infcx().type_var_diverges(ty) { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil()); - } else { - match self.infcx().type_is_unconstrained_numeric(ty) { - UnconstrainedInt => { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32) - }, - UnconstrainedFloat => { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64) - } - Neither => { - if let Some(default) = default_map.get(ty) { - let default = default.clone(); - match infer::mk_eqty(self.infcx(), false, - infer::Misc(default.origin_span), - ty, default.ty) { - Ok(()) => {} - Err(_) => { - conflicts.push((*ty, default)); - } - } - } - } + for &(ref ty, ref default) in &has_user_default { + let default = default.clone(); + + let normalized_default = self.inh.normalize_associated_types_in( + default.origin_span, + 0, &default.ty); + + match infer::mk_eqty(self.infcx(), false, + infer::Misc(default.origin_span), + ty, normalized_default) { + Ok(()) => {} + Err(_) => { + conflicts.push((*ty, default)); } } } @@ -1938,15 +1899,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if conflicts.len() > 0 { // 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 { + for conflict in conflicts { let conflicting_default = - self.find_conflicting_default(&unbound_tyvars, &default_map, conflict) - .unwrap_or(type_variable::Default { + self.find_conflicting_default(&has_user_default, &conflict) + .unwrap_or(type_variable::UserDefault { ty: self.infcx().next_ty_var(), origin_span: codemap::DUMMY_SP, def_id: DefId::local(0) // what do I put here? }); + let default = conflict.1; + // 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. @@ -1964,6 +1927,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { second_default) } } + + // Apply integer and floating point fallbacks to any variables that + // weren't solved by the previous phase where we applied user defaults. + for ty in &has_literal_fallback { + let resolved = self.infcx().resolve_type_vars_if_possible(ty); + match self.infcx().type_is_unconstrained_numeric(resolved) { + UnconstrainedInt => { + demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32) + }, + UnconstrainedFloat => { + demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64) + } + Neither => {} + } + } + + // Finally for any leftover variables that diverage + // we should apply the unit fallback rules. + for ty in &is_diverging { + if self.infcx().type_var_diverges(ty) { + demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil()); + } + } } self.select_obligations_where_possible(); @@ -1974,17 +1960,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // table then apply defaults until we find a conflict. That default must be the one // that caused conflict earlier. fn find_conflicting_default(&self, - unbound_vars: &HashSet>, - default_map: &FnvHashMap<&Ty<'tcx>, type_variable::Default<'tcx>>, - conflict: Ty<'tcx>) - -> Option> { - use middle::ty::error::UnconstrainedNumeric::Neither; - use middle::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; - + tys_with_defaults: &HashSet<(Ty<'tcx>, type_variable::UserDefault<'tcx>)>, + conflict: &(Ty<'tcx>, type_variable::UserDefault<'tcx>)) + -> Option> { // Ensure that we apply the conflicting default first - let mut unbound_tyvars = Vec::with_capacity(unbound_vars.len() + 1); + let mut unbound_tyvars = Vec::with_capacity(tys_with_defaults.len() + 1); unbound_tyvars.push(conflict); - unbound_tyvars.extend(unbound_vars.iter()); + unbound_tyvars.extend(tys_with_defaults.iter()); let mut result = None; // We run the same code as above applying defaults in order, this time when @@ -1992,30 +1974,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We also run this inside snapshot that never commits so we can do error // reporting for more then one conflict. - for ty in &unbound_tyvars { - if self.infcx().type_var_diverges(ty) { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil()); - } else { - match self.infcx().type_is_unconstrained_numeric(ty) { - UnconstrainedInt => { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.i32) - }, - UnconstrainedFloat => { - demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().types.f64) - }, - Neither => { - if let Some(default) = default_map.get(ty) { - let default = default.clone(); - match infer::mk_eqty(self.infcx(), false, - infer::Misc(default.origin_span), - ty, default.ty) { - Ok(()) => {} - Err(_) => { - result = Some(default); - } - } - } - } + for &(ref ty, ref default) in tys_with_defaults { + let default = default.clone(); + + let normalized_default = self.inh.normalize_associated_types_in( + default.origin_span, 0, + &default.ty); + + match infer::mk_eqty(self.infcx(), false, + infer::Misc(default.origin_span), + ty, normalized_default) { + Ok(()) => {} + Err(_) => { + result = Some(default); + break; } } } diff --git a/src/test/compile-fail/default_ty_param_conflict.rs b/src/test/compile-fail/default_ty_param_fallback_conflict.rs similarity index 100% rename from src/test/compile-fail/default_ty_param_conflict.rs rename to src/test/compile-fail/default_ty_param_fallback_conflict.rs diff --git a/src/test/compile-fail/default_ty_param_conflict_cross_crate.rs b/src/test/compile-fail/default_ty_param_fallback_conflict_cross_crate.rs similarity index 100% rename from src/test/compile-fail/default_ty_param_conflict_cross_crate.rs rename to src/test/compile-fail/default_ty_param_fallback_conflict_cross_crate.rs diff --git a/src/test/run-pass/default_ty_param_default_dependent_associated_type.rs b/src/test/run-pass/default_ty_param_fallback_default_dependent_associated_type.rs similarity index 100% rename from src/test/run-pass/default_ty_param_default_dependent_associated_type.rs rename to src/test/run-pass/default_ty_param_fallback_default_dependent_associated_type.rs diff --git a/src/test/run-pass/default_ty_param_fallback_default_over_literal_fallback.rs b/src/test/run-pass/default_ty_param_fallback_default_over_literal_fallback.rs new file mode 100755 index 0000000000000..bc5478240a272 --- /dev/null +++ b/src/test/run-pass/default_ty_param_fallback_default_over_literal_fallback.rs @@ -0,0 +1,15 @@ +// 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)] + +fn foo(t: T) -> usize { std::mem::size_of_val(&t) } + +fn main() { assert_eq!(foo(22), std::mem::size_of::()) } diff --git a/src/test/run-pass/default_ty_param_dependent_defaults.rs b/src/test/run-pass/default_ty_param_fallback_dependent_defaults.rs similarity index 100% rename from src/test/run-pass/default_ty_param_dependent_defaults.rs rename to src/test/run-pass/default_ty_param_fallback_dependent_defaults.rs diff --git a/src/test/run-pass/default_ty_param_fallback_ensure_normalization.rs b/src/test/run-pass/default_ty_param_fallback_ensure_normalization.rs new file mode 100644 index 0000000000000..bc9e309563ef6 --- /dev/null +++ b/src/test/run-pass/default_ty_param_fallback_ensure_normalization.rs @@ -0,0 +1,16 @@ +// 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)] +#![feature(iter_arith)] + +fn main() { + print!("{}", (1..4).sum()); +} diff --git a/src/test/run-pass/default_ty_param_method_call_test.rs b/src/test/run-pass/default_ty_param_fallback_method_call_test.rs similarity index 100% rename from src/test/run-pass/default_ty_param_method_call_test.rs rename to src/test/run-pass/default_ty_param_fallback_method_call_test.rs diff --git a/src/test/run-pass/default_ty_param_struct.rs b/src/test/run-pass/default_ty_param_fallback_struct.rs similarity index 100% rename from src/test/run-pass/default_ty_param_struct.rs rename to src/test/run-pass/default_ty_param_fallback_struct.rs diff --git a/src/test/run-pass/default_ty_param_struct_and_type_alias.rs b/src/test/run-pass/default_ty_param_fallback_struct_and_type_alias.rs similarity index 100% rename from src/test/run-pass/default_ty_param_struct_and_type_alias.rs rename to src/test/run-pass/default_ty_param_fallback_struct_and_type_alias.rs diff --git a/src/test/run-pass/default_ty_param_trait_impl.rs b/src/test/run-pass/default_ty_param_fallback_trait_impl.rs similarity index 100% rename from src/test/run-pass/default_ty_param_trait_impl.rs rename to src/test/run-pass/default_ty_param_fallback_trait_impl.rs diff --git a/src/test/run-pass/default_ty_param_trait_impl_simple.rs b/src/test/run-pass/default_ty_param_fallback_trait_impl_simple.rs similarity index 100% rename from src/test/run-pass/default_ty_param_trait_impl_simple.rs rename to src/test/run-pass/default_ty_param_fallback_trait_impl_simple.rs diff --git a/src/test/run-pass/default_ty_param_type_alias.rs b/src/test/run-pass/default_ty_param_fallback_type_alias.rs similarity index 100% rename from src/test/run-pass/default_ty_param_type_alias.rs rename to src/test/run-pass/default_ty_param_fallback_type_alias.rs