diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index dfa675f2e9351..d73ddaec0bbb0 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -279,10 +279,10 @@ impl DefPath { let mut data = vec![]; let mut index = Some(start_index); loop { - debug!("DefPath::make: krate={:?} index={:?}", krate, index); + trace!("DefPath::make: krate={:?} index={:?}", krate, index); let p = index.unwrap(); let key = get_key(p); - debug!("DefPath::make: key={:?}", key); + trace!("DefPath::make: key={:?}", key); match key.disambiguated_data.data { DefPathData::CrateRoot => { assert!(key.parent.is_none()); diff --git a/src/librustc/ich/impls_ty.rs b/src/librustc/ich/impls_ty.rs index 9609ae5a0beb8..1b8073b15b189 100644 --- a/src/librustc/ich/impls_ty.rs +++ b/src/librustc/ich/impls_ty.rs @@ -462,11 +462,19 @@ for ty::RegionParameterDef { } } +impl_stable_hash_for!(enum ty::OriginOfTyParam { + Fn, + Impl, + TyDef, + Other +}); + impl_stable_hash_for!(struct ty::TypeParameterDef { name, def_id, index, has_default, + origin, object_lifetime_default, pure_wrt_drop, synthetic diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs index 50a37e12531a7..d0d446530f199 100644 --- a/src/librustc/infer/combine.rs +++ b/src/librustc/infer/combine.rs @@ -424,7 +424,8 @@ impl<'cx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx> for Generalizer<'cx, 'gcx, ' } let origin = variables.origin(vid); - let new_var_id = variables.new_var(false, origin, None); + let default = variables.default(vid).as_user().clone(); + let new_var_id = variables.new_var(false, origin, default); let u = self.tcx().mk_var(new_var_id); debug!("generalize: replacing original vid={:?} with new={:?}", vid, u); diff --git a/src/librustc/infer/error_reporting/need_type_info.rs b/src/librustc/infer/error_reporting/need_type_info.rs index ea3c0a8ddb450..1d33c3aefac72 100644 --- a/src/librustc/infer/error_reporting/need_type_info.rs +++ b/src/librustc/infer/error_reporting/need_type_info.rs @@ -75,8 +75,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { fn extract_type_name(&self, ty: &'a Ty<'tcx>) -> String { if let ty::TyInfer(ty::TyVar(ty_vid)) = (*ty).sty { let ty_vars = self.type_variables.borrow(); - if let TypeVariableOrigin::TypeParameterDefinition(_, name) = - *ty_vars.var_origin(ty_vid) { + if let TypeVariableOrigin::TypeParameterDefinition(_, name, _) = + ty_vars.var_origin(ty_vid) { name.to_string() } else { ty.to_string() diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs index 756a6947ee3f8..b81e6db60069a 100644 --- a/src/librustc/infer/fudge.rs +++ b/src/librustc/infer/fudge.rs @@ -111,7 +111,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub struct RegionFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { infcx: &'a InferCtxt<'a, 'gcx, 'tcx>, - type_variables: &'a TypeVariableMap, + type_variables: &'a TypeVariableMap<'tcx>, region_vars: &'a Vec, origin: &'a RegionVariableOrigin, } @@ -135,11 +135,11 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> { ty } - Some(&origin) => { + Some(&(origin, ref default)) => { // This variable was created during the // fudging. Recreate it with a fresh variable // here. - self.infcx.next_ty_var(origin) + self.infcx.next_ty_var_with_default(default.clone(), origin) } } } diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 7302bad0ca166..7e6f61e6d5dfd 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -695,23 +695,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, '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. - /// - /// 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> { - match ty.sty { - ty::TyInfer(ty::TyVar(vid)) => self.type_variables.borrow().default(vid), - _ => 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_fallback(&self) -> Vec> { let mut variables = Vec::new(); let unbound_ty_vars = self.type_variables @@ -737,7 +727,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { variables.extend(unbound_float_vars); return variables; - } +} fn combine_fields(&'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>) -> CombineFields<'a, 'gcx, 'tcx> { @@ -1032,6 +1022,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { .new_var(diverging, origin, None) } + pub fn next_ty_var_with_default(&self, + default: Option>, + origin: TypeVariableOrigin) -> Ty<'tcx> { + let ty_var_id = self.type_variables + .borrow_mut() + .new_var(false, origin, default); + + self.tcx.mk_var(ty_var_id) + } + pub fn next_ty_var(&self, origin: TypeVariableOrigin) -> Ty<'tcx> { self.tcx.mk_var(self.next_ty_var_id(false, origin)) } @@ -1093,7 +1093,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { -> Ty<'tcx> { let default = if def.has_default { let default = self.tcx.type_of(def.def_id); - Some(type_variable::Default { + Some(type_variable::UserDefault { ty: default.subst_spanned(self.tcx, substs, Some(span)), origin_span: span, def_id: def.def_id @@ -1102,14 +1102,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { None }; + let origin = TypeVariableOrigin::TypeParameterDefinition(span, + def.name, + def.origin); - let ty_var_id = self.type_variables - .borrow_mut() - .new_var(false, - TypeVariableOrigin::TypeParameterDefinition(span, def.name), - default); - - self.tcx.mk_var(ty_var_id) + self.tcx.mk_var(self.type_variables.borrow_mut().new_var(false, origin, default)) } /// Given a set of generics defined on a type or impl, returns a substitution mapping each @@ -1361,13 +1358,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { pub fn report_conflicting_default_types(&self, span: Span, body_id: ast::NodeId, - expected: type_variable::Default<'tcx>, - actual: type_variable::Default<'tcx>) { + expected: type_variable::UserDefault<'tcx>, + actual: type_variable::UserDefault<'tcx>) { let trace = TypeTrace { cause: ObligationCause::misc(span, body_id), values: Types(ExpectedFound { expected: expected.ty, - found: actual.ty + found: actual.ty, }) }; diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs index 6aa094d2cd6d7..257f509eec845 100644 --- a/src/librustc/infer/type_variable.rs +++ b/src/librustc/infer/type_variable.rs @@ -55,7 +55,7 @@ pub enum TypeVariableOrigin { MiscVariable(Span), NormalizeProjectionType(Span), TypeInference(Span), - TypeParameterDefinition(Span, ast::Name), + TypeParameterDefinition(Span, ast::Name, ty::OriginOfTyParam), /// one of the upvars or closure kind parameters in a `ClosureSubsts` /// (before it has been determined) @@ -70,25 +70,44 @@ pub enum TypeVariableOrigin { Generalized(ty::TyVid), } -pub type TypeVariableMap = FxHashMap; +pub type TypeVariableMap<'tcx> = FxHashMap>)>; struct TypeVariableData<'tcx> { value: TypeVariableValue<'tcx>, origin: TypeVariableOrigin, - diverging: bool + default: Default<'tcx>, } enum TypeVariableValue<'tcx> { Known(Ty<'tcx>), - Bounded { - default: Option> + Bounded, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum Default<'tcx> { + User(UserDefault<'tcx>), + Integer, + Float, + Diverging, + None, +} + +impl<'tcx> Default<'tcx> { + pub fn as_user(&self) -> Option> { + match *self { + Default::User(ref user_default) => Some(user_default.clone()), + Default::None => None, + _ => bug!("Default exists but is not user"), + } } } -// We will use this to store the required information to recapitulate what happened when -// an error occurs. +// 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 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, @@ -102,9 +121,8 @@ pub struct Snapshot { sub_snapshot: ut::Snapshot, } -struct Instantiate<'tcx> { +struct Instantiate { vid: ty::TyVid, - default: Option>, } struct Delegate<'tcx>(PhantomData<&'tcx ()>); @@ -118,19 +136,19 @@ impl<'tcx> TypeVariableTable<'tcx> { } } - 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, + } } - pub fn var_origin(&self, vid: ty::TyVid) -> &TypeVariableOrigin { - &self.values.get(vid.index as usize).origin + pub fn var_origin(&self, vid: ty::TyVid) -> TypeVariableOrigin { + self.values.get(vid.index as usize).origin } /// Records that `a == b`, depending on `dir`. @@ -165,8 +183,8 @@ impl<'tcx> TypeVariableTable<'tcx> { }; match old_value { - TypeVariableValue::Bounded { default } => { - self.values.record(Instantiate { vid: vid, default: default }); + TypeVariableValue::Bounded => { + self.values.record(Instantiate { vid: vid }); } TypeVariableValue::Known(old_ty) => { bug!("instantiating type variable `{:?}` twice: new-value = {:?}, old-value={:?}", @@ -178,14 +196,22 @@ impl<'tcx> TypeVariableTable<'tcx> { pub fn new_var(&mut self, diverging: bool, origin: TypeVariableOrigin, - default: Option>,) -> ty::TyVid { - debug!("new_var(diverging={:?}, origin={:?})", diverging, origin); + default: Option>,) -> ty::TyVid { + debug!("new_var(diverging={:?}, origin={:?} default={:?})", diverging, origin, default); self.eq_relations.new_key(()); self.sub_relations.new_key(()); + + 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 { default: default }, + value: Bounded, origin, - diverging, + default, }); let v = ty::TyVid { index: index as u32 }; debug!("new_var: diverging={:?} index={:?}", diverging, v); @@ -235,7 +261,7 @@ impl<'tcx> TypeVariableTable<'tcx> { pub fn probe_root(&mut self, vid: ty::TyVid) -> Option> { debug_assert!(self.root_var(vid) == vid); match self.values.get(vid.index as usize).value { - Bounded { .. } => None, + Bounded => None, Known(t) => Some(t) } } @@ -289,7 +315,7 @@ impl<'tcx> TypeVariableTable<'tcx> { /// ty-variables created during the snapshot, and the values /// `{V2}` are the root variables that they were unified with, /// along with their origin. - pub fn types_created_since_snapshot(&mut self, s: &Snapshot) -> TypeVariableMap { + pub fn types_created_since_snapshot(&mut self, s: &Snapshot) -> TypeVariableMap<'tcx> { let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot); actions_since_snapshot @@ -300,7 +326,8 @@ impl<'tcx> TypeVariableTable<'tcx> { }) .map(|vid| { let origin = self.values.get(vid.index as usize).origin.clone(); - (vid, origin) + let default = self.default(vid).clone().as_user(); + (vid, (origin, default)) }) .collect() } @@ -331,12 +358,12 @@ impl<'tcx> TypeVariableTable<'tcx> { debug!("NewElem({}) new_elem_threshold={}", index, new_elem_threshold); } - sv::UndoLog::Other(Instantiate { vid, .. }) => { + sv::UndoLog::Other(Instantiate { vid }) => { if vid.index < new_elem_threshold { // quick check to see if this variable was // created since the snapshot started or not. let escaping_type = match self.values.get(vid.index as usize).value { - Bounded { .. } => bug!(), + Bounded => bug!(), Known(ty) => ty, }; escaping_types.push(escaping_type); @@ -367,12 +394,10 @@ impl<'tcx> TypeVariableTable<'tcx> { impl<'tcx> sv::SnapshotVecDelegate for Delegate<'tcx> { type Value = TypeVariableData<'tcx>; - type Undo = Instantiate<'tcx>; + type Undo = Instantiate; - fn reverse(values: &mut Vec>, action: Instantiate<'tcx>) { - let Instantiate { vid, default } = action; - values[vid.index as usize].value = Bounded { - default, - }; + fn reverse(values: &mut Vec>, action: Instantiate) { + let Instantiate { vid } = action; + values[vid.index as usize].value = Bounded; } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 46ec2be4a1f9b..8cabd2ebce116 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -36,7 +36,7 @@ use middle::const_val; use std::fmt; use syntax::ast; use session::DiagnosticMessageId; -use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; +use ty::{self, AdtKind, OriginOfTyParam, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::ExpectedFound; use ty::fast_reject; use ty::fold::TypeFolder; @@ -1134,7 +1134,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let infcx = self.infcx; self.var_map.entry(ty).or_insert_with(|| infcx.next_ty_var( - TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, name))) + TypeVariableOrigin::TypeParameterDefinition(DUMMY_SP, + name, + OriginOfTyParam::Other))) } else { ty.super_fold_with(self) } diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs index 6b681322c9bf5..f5b560294a643 100644 --- a/src/librustc/traits/fulfill.rs +++ b/src/librustc/traits/fulfill.rs @@ -9,12 +9,13 @@ // except according to those terms. use infer::{RegionObligation, InferCtxt, InferOk}; -use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate}; +use ty::{self, Ty, TypeFoldable, ToPolyTraitRef, ToPredicate, InferTy, TypeVariants}; use ty::error::ExpectedFound; use rustc_data_structures::obligation_forest::{ObligationForest, Error}; use rustc_data_structures::obligation_forest::{ForestObligation, ObligationProcessor}; use std::marker::PhantomData; use hir::def_id::DefId; +use util::nodemap::FxHashSet; use super::CodeAmbiguity; use super::CodeProjectionError; @@ -41,7 +42,7 @@ impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> { /// along. Once all type inference constraints have been generated, the /// method `select_all_or_error` can be used to report any remaining /// ambiguous cases as errors. - +#[derive(Clone)] pub struct FulfillmentContext<'tcx> { // A list of all obligations that have been registered with this // fulfillment context. @@ -179,6 +180,18 @@ impl<'a, 'gcx, 'tcx> FulfillmentContext<'tcx> { self.predicates.pending_obligations() } + pub fn vars_in_obligations(&self) -> FxHashSet { + let mut vars = FxHashSet(); + for p in self.predicates.obligations() { + for ty in p.obligation.predicate.walk_tys() { + if let TypeVariants::TyInfer(InferTy::TyVar(vid)) = ty.sty { + vars.insert(vid); + } + } + } + vars + } + /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it /// only attempts to select obligations that haven't been seen before. fn select(&mut self, selcx: &mut SelectionContext<'a, 'gcx, 'tcx>) diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index cb68e576e5af9..912c2e5bd8b80 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -56,7 +56,7 @@ pub enum TypeError<'tcx> { CyclicTy(Ty<'tcx>), ProjectionMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), - TyParamDefaultMismatch(ExpectedFound>), + TyParamDefaultMismatch(ExpectedFound>), ExistentialMismatch(ExpectedFound<&'tcx ty::Slice>>), OldStyleLUB(Box>), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 583dcb46f000c..d03df792353e5 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -671,12 +671,21 @@ pub enum IntVarValue { UintType(ast::UintTy), } +#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)] +pub enum OriginOfTyParam { + Fn, + Impl, + TyDef, + Other, +} + #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub struct TypeParameterDef { pub name: Name, pub def_id: DefId, pub index: u32, pub has_default: bool, + pub origin: OriginOfTyParam, pub object_lifetime_default: ObjectLifetimeDefault, /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 438511281ba47..72170ad37492f 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -548,8 +548,8 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::error::ExpectedFound { } BraceStructLiftImpl! { - impl<'a, 'tcx> Lift<'tcx> for type_variable::Default<'a> { - type Lifted = type_variable::Default<'tcx>; + impl<'a, 'tcx> Lift<'tcx> for type_variable::UserDefault<'a> { + type Lifted = type_variable::UserDefault<'tcx>; ty, origin_span, def_id } } @@ -1172,9 +1172,9 @@ impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFoun } } -impl<'tcx> TypeFoldable<'tcx> for type_variable::Default<'tcx> { +impl<'tcx> TypeFoldable<'tcx> for type_variable::UserDefault<'tcx> { fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self { - type_variable::Default { + type_variable::UserDefault { ty: self.ty.fold_with(folder), origin_span: self.origin_span, def_id: self.def_id diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 02cae52166ac3..6376755e21a6a 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -57,6 +57,7 @@ pub trait ObligationProcessor { where I: Clone + Iterator; } +#[derive(Clone)] pub struct ObligationForest { /// The list of obligations. In between calls to /// `process_obligations`, this list only contains nodes in the @@ -81,7 +82,7 @@ pub struct ObligationForest { scratch: Option>, } -#[derive(Debug)] +#[derive(Clone, Debug)] struct Node { obligation: O, state: Cell, @@ -244,6 +245,13 @@ impl ObligationForest { .collect() } + /// Returns all obligations. + pub fn obligations(&self) -> Vec + where O: Clone + { + self.nodes.iter().map(|n| n.obligation.clone()).collect() + } + /// Perform a pass through the obligation list. This must /// be called in a loop until `outcome.stalled` is false. /// diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 8b849a9e52f3a..98e0bc60675e5 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -244,20 +244,30 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { return ty; } + let inferred_param = || if !default_needs_object_self(def) { + self.ty_infer_for_def(def, substs, span) + } else { + self.ty_infer(span) + }; + let i = i - self_ty.is_some() as usize - decl_generics.regions.len(); if i < num_types_provided { // A provided type parameter. - self.ast_ty_to_ty(¶meters.types[i]) + let provided = ¶meters.types[i]; + if provided.node != hir::Ty_::TyInfer { + self.ast_ty_to_ty(provided) + } else { + let inferred = inferred_param(); + self.record_ty(provided.hir_id, inferred, provided.span); + inferred + } } else if infer_types { // No type parameters were provided, we can infer all. - let ty_var = if !default_needs_object_self(def) { - self.ty_infer_for_def(def, substs, span) - } else { - self.ty_infer(span) - }; - ty_var + inferred_param() } else if def.has_default { // No type parameter provided, but a default exists. + // FIXME(leodasvacas): + // For fns and impls, feature gate under `default_type_parameter_fallback`. // If we are converting an object type, then the // `Self` parameter is unknown. However, some of the @@ -706,6 +716,18 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { span) } + fn count_bounds_for_assoc_item(&self, + ty_param_def_id: DefId, + assoc_name: ast::Name, + span: Span) + -> usize + { + let tcx = self.tcx(); + let bounds: Vec<_> = self.get_type_parameter_bounds(span, ty_param_def_id) + .predicates.into_iter().filter_map(|p| p.to_opt_poly_trait_ref()).collect(); + traits::transitive_bounds(tcx, &bounds) + .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name)).count() + } // Checks that bounds contains exactly one element and reports appropriate // errors otherwise. @@ -777,6 +799,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { item_segment: &hir::PathSegment) -> (Ty<'tcx>, Def) { + use rustc::ty::ToPolyTraitRef; + let tcx = self.tcx(); let assoc_name = item_segment.name; @@ -808,9 +832,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { Err(ErrorReported) => return (tcx.types.err, Def::Err), } } - (&ty::TyParam(_), Def::SelfTy(Some(param_did), None)) | - (&ty::TyParam(_), Def::TyParam(param_did)) => { - match self.find_bound_for_assoc_item(param_did, assoc_name, span) { + (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) + if self.count_bounds_for_assoc_item(trait_did, assoc_name, span) == 0 => { + // No bounds for `Self` in trait definition. + let substs = Substs::identity_for_item(tcx, trait_did); + let trait_ref = ty::TraitRef::new(trait_did, substs).to_poly_trait_ref(); + let candidates = + traits::supertraits(tcx, trait_ref) + .filter(|r| self.trait_defines_associated_type_named(r.def_id(), + assoc_name)); + match self.one_bound_for_assoc_type(candidates, "Self", assoc_name, span) { + Ok(bound) => bound, + Err(ErrorReported) => return (tcx.types.err, Def::Err), + } + } + (&ty::TyParam(_), Def::SelfTy(Some(did), None)) | + (&ty::TyParam(_), Def::TyParam(did)) => { + match self.find_bound_for_assoc_item(did, assoc_name, span) { Ok(bound) => bound, Err(ErrorReported) => return (tcx.types.err, Def::Err), } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 17ed0aaa30b02..81d63511afcad 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -304,6 +304,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { // Create subst for early-bound lifetime parameters, combining // parameters from the type and those from the method. + // FIXME(leodasvacas): + // Support substituting elided for defaults under gate `default_type_parameter_fallback`. assert_eq!(method_generics.parent_count(), parent_substs.len()); let provided = &segment.parameters; Substs::for_item(self.tcx, pick.item.def_id, |def, _| { @@ -325,7 +327,13 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> { p.types.get(i - parent_substs.len() - method_generics.regions.len()) }) { - self.to_ty(ast_ty) + if ast_ty.node != hir::Ty_::TyInfer { + self.to_ty(ast_ty) + } else { + let inferred = self.type_var_for_def(self.span, def, cur_substs); + self.record_ty(ast_ty.hir_id, inferred, ast_ty.span); + inferred + } } else { self.type_var_for_def(self.span, def, cur_substs) } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 09dd334a62d8a..3941c82e63f5a 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -90,7 +90,7 @@ use hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_back::slice::ref_slice; use namespace::Namespace; use rustc::infer::{self, InferCtxt, InferOk, RegionVariableOrigin}; -use rustc::infer::type_variable::{TypeVariableOrigin}; +use rustc::infer::type_variable::TypeVariableOrigin; use rustc::middle::region; use rustc::ty::subst::{Kind, Subst, Substs}; use rustc::traits::{self, FulfillmentContext, ObligationCause, ObligationCauseCode}; @@ -2131,11 +2131,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } - /// Apply "fallbacks" to some types - /// unconstrained types get replaced with ! or () (depending on whether + /// Apply divering and numeric fallbacks. + /// Diverging types get replaced with ! or () (depending on whether /// feature(never_type) is enabled), unconstrained ints with i32, and /// unconstrained floats with f64. - fn default_type_parameters(&self) { + fn apply_diverging_and_numeric_type_parameter_fallback(&self) { use rustc::ty::error::UnconstrainedNumeric::Neither; use rustc::ty::error::UnconstrainedNumeric::{UnconstrainedInt, UnconstrainedFloat}; @@ -2144,7 +2144,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // some errors in this function, just resolve all uninstanted type // varibles to TyError. if self.is_tainted_by_errors() { - for ty in &self.unsolved_variables() { + for ty in &self.candidates_for_fallback() { if let ty::TyInfer(_) = self.shallow_resolve(ty).sty { debug!("default_type_parameters: defaulting `{:?}` to error", ty); self.demand_eqtype(syntax_pos::DUMMY_SP, *ty, self.tcx().types.err); @@ -2153,7 +2153,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { return; } - for ty in &self.unsolved_variables() { + for ty in &self.candidates_for_fallback() { let resolved = self.resolve_type_vars_if_possible(ty); if self.type_var_diverges(resolved) { debug!("default_type_parameters: defaulting `{:?}` to `!` because it diverges", @@ -2178,10 +2178,105 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } } + /// This runs as the last resort of type inference. + /// + /// It applies user supplied defaults as fallbacks for inference variables, + /// for example in `fn foo()` an inference variable originated from `T` + /// will have `String` as its default. + /// + /// Adding a default to a type parameter that has none should be backwards compatible. + /// Therefore we take care to future-proof against conflicting defaults. + /// + /// Currently we prioritize params from impls and fns over params in types, + /// this for example allows `fn foo(x: Option)` to work + /// even though `Option` has no default for `T`. + /// Lower priority defaults are considered when there are no higher priority params involved. + fn apply_user_type_parameter_fallback(&self) { + use self::TypeVariableOrigin::TypeParameterDefinition; + use ty::OriginOfTyParam; + // Collect variables that are unsolved and support fallback, + // grouped in bags by subtyping equivalence. + let mut bags = FxHashMap(); + for vid in self.fulfillment_cx.borrow().vars_in_obligations() { + let mut type_variables = self.infcx.type_variables.borrow_mut(); + let not_known = type_variables.probe(vid).is_none(); + let supports_fallback = match type_variables.var_origin(vid) { + TypeParameterDefinition(_, _, OriginOfTyParam::Fn) | + TypeParameterDefinition(_, _, OriginOfTyParam::Impl) | + TypeParameterDefinition(_, _, OriginOfTyParam::TyDef) => true, + _ => false + }; + if supports_fallback && not_known { + let root = type_variables.sub_root_var(vid); + bags.entry(root).or_insert(Vec::new()).push(vid); + } + } + // We put everything in a single transaction + // because dependent defaults create cross-bag dependencies. + // This is bad in that we may report errors + // for things that actually were successfully inferred. + let _ = self.commit_if_ok(|_| { self.save_and_restore_in_snapshot_flag(|infcx| { + // Clone the whole thing so we can use it for this snapshot. + let mut local_fullfilment = self.fulfillment_cx.borrow().clone(); + // Attempt to find a fallback for each bag. + // - Fail if there are missing defaults. + // - Apply default if all default exist. + 'bags: for bag in bags.into_iter().map(|b| b.1) { + // Partition the bag by the origin of the type param. + let (fn_or_impl, ty_def) = bag.iter().partition(|&&v| { + match infcx.type_variables.borrow().var_origin(v) { + TypeParameterDefinition(_, _, OriginOfTyParam::Fn) | + TypeParameterDefinition(_, _, OriginOfTyParam::Impl) => true, + TypeParameterDefinition(_, _, OriginOfTyParam::TyDef) => false, + _ => bug!("type var does not support fallback") + } + }); + // Params from fns or impls have higher priority than those from type definitions. + // The first non-empty priority level is considered. + let mut bag: Vec = fn_or_impl; + if bag.is_empty() { + bag = ty_def; + } + let get_default = |&v| infcx.type_variables.borrow().default(v).as_user(); + let mut normalized_defaults = Vec::new(); + for (&vid, default) in bag.iter().zip(bag.iter().map(&get_default)) { + if let Some(d) = default { + let infr_ok = self.normalize_associated_types_in_as_infer_ok(d.origin_span, + &d.ty); + normalized_defaults.push((vid, infr_ok.value)); + for obligation in infr_ok.obligations { + local_fullfilment.register_predicate_obligation(infcx, obligation); + } + } else { + continue 'bags; // Fail, missing default. + } + } + // All defaults exist, apply them. + for (vid, default) in normalized_defaults { + let ty = self.tcx.mk_var(vid); + let cause = self.misc(syntax_pos::DUMMY_SP); + if let Ok(infer_ok) = self.at(&cause, self.param_env).sub(default, ty) { + for obligation in infer_ok.obligations { + local_fullfilment.register_predicate_obligation(infcx, obligation); + } + } + debug!("apply_user_type_parameter_fallback: applied fallback to var: {:?} \ + with ty: {:?} with default: {:?}", vid, ty, default); + } + } + // Rollback on any conflict. + if local_fullfilment.select_where_possible(self).is_err() { + Err(()) + } else { + Ok(()) + } + })}); + } + // Implements type inference fallback algorithm fn select_all_obligations_and_apply_defaults(&self) { self.select_obligations_where_possible(); - self.default_type_parameters(); + self.apply_diverging_and_numeric_type_parameter_fallback(); self.select_obligations_where_possible(); } @@ -2193,6 +2288,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { assert!(self.deferred_call_resolutions.borrow().is_empty()); self.select_all_obligations_and_apply_defaults(); + if self.tcx.sess.features.borrow().default_type_parameter_fallback { + self.apply_user_type_parameter_fallback(); + } let mut fulfillment_cx = self.fulfillment_cx.borrow_mut(); @@ -4780,9 +4878,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { if let Some(ast_ty) = types.get(i) { // A provided type parameter. - self.to_ty(ast_ty) + if ast_ty.node != hir::Ty_::TyInfer { + self.to_ty(ast_ty) + } else { + let inferred = self.type_var_for_def(span, def, substs); + self.record_ty(ast_ty.hir_id, inferred, ast_ty.span); + inferred + } } else if !infer_types && def.has_default { // No type parameter provided, but a default exists. + // FIXME(leodasvacas): + // For fns and impls, feature gate under `default_type_parameter_fallback`. let default = self.tcx.type_of(def.def_id); self.normalize_ty( span, @@ -4990,6 +5096,14 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // If not, error. if alternative.is_ty_var() || alternative.references_error() { if !self.is_tainted_by_errors() { + // Try user fallbacks as a last attempt. + if self.tcx.sess.features.borrow().default_type_parameter_fallback { + self.apply_user_type_parameter_fallback(); + let ty = self.resolve_type_vars_with_obligations(ty); + if !ty.is_ty_var() { + return ty; + } + } type_error_struct!(self.tcx.sess, sp, ty, E0619, "the type of this value must be known in this context") .emit(); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 7de29868d4341..11e2ad7c4e7b3 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -872,32 +872,47 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut opt_self = None; let mut allow_defaults = false; + let mut origin = ty::OriginOfTyParam::Other; let no_generics = hir::Generics::empty(); let (ast_generics, opt_inputs) = match node { NodeTraitItem(item) => { match item.node { - TraitItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)), + TraitItemKind::Method(ref sig, _) => { + origin = ty::OriginOfTyParam::Fn; + (&item.generics, Some(&sig.decl.inputs)) + } _ => (&item.generics, None) } } NodeImplItem(item) => { match item.node { - ImplItemKind::Method(ref sig, _) => (&item.generics, Some(&sig.decl.inputs)), + ImplItemKind::Method(ref sig, _) => { + origin = ty::OriginOfTyParam::Fn; + (&item.generics, Some(&sig.decl.inputs)) + } _ => (&item.generics, None) } } NodeItem(item) => { match item.node { - ItemFn(ref decl, .., ref generics, _) => (generics, Some(&decl.inputs)), - ItemImpl(_, _, _, ref generics, ..) => (generics, None), + ItemFn(ref decl, .., ref generics, _) => { + origin = ty::OriginOfTyParam::Fn; + (generics, Some(&decl.inputs)) + } + + ItemImpl(_, _, _, ref generics, ..) => { + origin = ty::OriginOfTyParam::Impl; + (generics, None) + } ItemTy(_, ref generics) | ItemEnum(_, ref generics) | ItemStruct(_, ref generics) | ItemUnion(_, ref generics) => { + origin = ty::OriginOfTyParam::TyDef; allow_defaults = true; (generics, None) } @@ -914,6 +929,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: keywords::SelfType.name(), def_id: tcx.hir.local_def_id(param_id), has_default: false, + origin: ty::OriginOfTyParam::Other, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, synthetic: None, @@ -990,6 +1006,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: p.name, def_id: tcx.hir.local_def_id(p.id), has_default: p.default.is_some(), + origin, object_lifetime_default: object_lifetime_defaults.as_ref().map_or(rl::Set1::Empty, |o| o[i]), pure_wrt_drop: p.pure_wrt_drop, @@ -1008,6 +1025,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Symbol::intern(&tcx.hir.node_to_pretty_string(info.id)), def_id: info.def_id, has_default: false, + origin: ty::OriginOfTyParam::Other, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, synthetic: Some(SyntheticTyParamKind::ImplTrait), @@ -1025,6 +1043,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Symbol::intern(""), def_id, has_default: false, + origin: ty::OriginOfTyParam::Other, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, synthetic: None, @@ -1036,6 +1055,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Symbol::intern(""), def_id, has_default: false, + origin: ty::OriginOfTyParam::Other, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, synthetic: None, @@ -1047,6 +1067,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Symbol::intern(""), def_id, has_default: false, + origin: ty::OriginOfTyParam::Other, object_lifetime_default: rl::Set1::Empty, pure_wrt_drop: false, synthetic: None, diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 3464db2a81111..18e181123c4b4 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -321,11 +321,11 @@ impl CodeMap { .sum(); col.0 - special_chars + non_narrow }; - debug!("byte pos {:?} is on the line at byte pos {:?}", + trace!("byte pos {:?} is on the line at byte pos {:?}", pos, linebpos); - debug!("char pos {:?} is on the line at char pos {:?}", + trace!("char pos {:?} is on the line at char pos {:?}", chpos, linechpos); - debug!("byte is on line: {}", line); + trace!("byte is on line: {}", line); assert!(chpos >= linechpos); Loc { file: f, diff --git a/src/test/run-fail/default_over_literal.rs b/src/test/run-fail/default_over_literal.rs new file mode 100644 index 0000000000000..b3d5c2eb7f906 --- /dev/null +++ b/src/test/run-fail/default_over_literal.rs @@ -0,0 +1,17 @@ +// 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. + +// error-pattern:assertion failed: `(left == right)` + +#![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-fallback/associated_type_as_default.rs b/src/test/run-pass/default-ty-param-fallback/associated_type_as_default.rs new file mode 100644 index 0000000000000..5a1d33a0fd48c --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/associated_type_as_default.rs @@ -0,0 +1,61 @@ +// 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. +// compile-flags: --error-format=human + +// 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::vec::IntoIter; +use std::iter::Sum; +use std::slice::Iter; +use std::ops::Add; + +trait Itarator: Iterator { + type Iten; + + fn foo(&self) -> T { + T::default() + } + + fn suma::Output>(self) -> S + where Self: Sized, + S: Sum, + { + Sum::sum(self) + } +} + +impl Itarator for IntoIter { + type Iten = as Iterator>::Item; +} + +impl<'a> Itarator for Iter<'a, u32> { + type Iten = as Iterator>::Item; +} + +fn main() { + let x = vec![0u32]; + { + let v = x.iter(); + v.suma() as u64; + } + x.clone().into_iter().suma(); + x.into_iter().suma(); +} diff --git a/src/test/run-pass/default-ty-param-fallback/dependent_associated_type.rs b/src/test/run-pass/default-ty-param-fallback/dependent_associated_type.rs new file mode 100644 index 0000000000000..80ef398a831b4 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/dependent_associated_type.rs @@ -0,0 +1,37 @@ +// 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 Me; +} + +impl Id for A { + type Me = A; +} + +struct Foo { + data: PhantomData<(X, Y, Z, W)>, +} + +impl::Me, Z = ::Me, W = Vec<::Me>> + Foo { + fn new() -> Foo { + Foo { data: PhantomData } + } +} + +fn main() { + let _ = Foo::new(); +} diff --git a/src/test/run-pass/default-ty-param-fallback/dependent_associated_type_equal.rs b/src/test/run-pass/default-ty-param-fallback/dependent_associated_type_equal.rs new file mode 100644 index 0000000000000..0b8e031e259b0 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/dependent_associated_type_equal.rs @@ -0,0 +1,44 @@ +// 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; + +#[derive(Copy, Clone)] +enum Opt { + Som(T), + Non, +} + +trait Id { + type Me; +} + +impl Id for A { + type Me = A; +} + +struct Foo { + data: PhantomData<(X, Y, Z)>, +} + +impl::Me, Z = ::Me> + Foo { + fn new(_: Opt, _: Opt, _: Opt) -> Foo { + Foo { data: PhantomData } + } +} + +fn main() { + let a = Opt::Non; + let _ = Foo::new(a, a, a); +} diff --git a/src/test/run-pass/default-ty-param-fallback/dependent_defaults.rs b/src/test/run-pass/default-ty-param-fallback/dependent_defaults.rs new file mode 100644 index 0000000000000..3b77caf963b6f --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/dependent_defaults.rs @@ -0,0 +1,26 @@ +// 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; + +#[allow(dead_code)] +struct Foo { t: T, data: PhantomData } + +impl Foo { + fn new(t: T) -> Foo { + Foo { t, data: PhantomData } + } +} + +fn main() { + let _ = Foo::new('a'); +} diff --git a/src/test/run-pass/default-ty-param-fallback/enum.rs b/src/test/run-pass/default-ty-param-fallback/enum.rs new file mode 100644 index 0000000000000..98cf71bde339b --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/enum.rs @@ -0,0 +1,38 @@ +// 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::path::Path; +use std::mem::size_of; + +enum Opt { + Som(T), + Non, +} + +fn main() { + // Defaults on the type definiton work, as long no other params are interfering. + let _ = Opt::Non; + let _: Opt<_> = Opt::Non; + + func1(None); + func2(Opt::Non); +} + +// Defaults on fns take precedence. +fn func1 = &'static str>(p: Option

) { + // Testing that we got &str rather than String. + assert_eq!(size_of::

(), size_of::<&str>()) +} + +fn func2 = &'static str>(p: Opt

) { + assert_eq!(size_of::

) { } +fn func2 = String>(p: Opt

) { } diff --git a/src/test/run-pass/default-ty-param-fallback/heterogeneous_partial_eq_for_option.rs b/src/test/run-pass/default-ty-param-fallback/heterogeneous_partial_eq_for_option.rs new file mode 100644 index 0000000000000..88e9ac0ea7e41 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/heterogeneous_partial_eq_for_option.rs @@ -0,0 +1,22 @@ +// 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)] + +trait PartialQe { + fn qe(&self, _: &Rhs) {} +} + +impl PartialQe> for Option {} + +fn main() { + PartialQe::qe(&Some("str"), &None); + Some('a').qe(&None); +} diff --git a/src/test/run-pass/default-ty-param-fallback/method_call.rs b/src/test/run-pass/default-ty-param-fallback/method_call.rs new file mode 100644 index 0000000000000..ecfd52475b2ca --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/method_call.rs @@ -0,0 +1,24 @@ +// 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 _ = Foo.method(); + Foo.method::<_>(); +} diff --git a/src/test/run-pass/default-ty-param-fallback/placeholder_type_hint.rs b/src/test/run-pass/default-ty-param-fallback/placeholder_type_hint.rs new file mode 100644 index 0000000000000..5c8637f2f3e1d --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/placeholder_type_hint.rs @@ -0,0 +1,22 @@ +// 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)] + +enum Opt { + Som(T), + Non, +} + +struct Foo(Opt); + +fn main() { + let _: Foo<_> = Foo(Opt::Non); +} diff --git a/src/test/run-pass/default-ty-param-fallback/related_dependent_defaults.rs b/src/test/run-pass/default-ty-param-fallback/related_dependent_defaults.rs new file mode 100644 index 0000000000000..8429b174376b1 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/related_dependent_defaults.rs @@ -0,0 +1,45 @@ +// 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. + +// 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)] + +#[derive(Copy, Clone)] +enum Opt { + Som(T), + Non, +} + +fn main() { + let a = Opt::Non; + let b = Opt::Non; + func1(a, b); + func2(b, a); + + let c = Opt::Non; + let d = Opt::Non; + func1(c, d); + func2(c, d); +} + +fn func1(_: Opt, _: Opt) { +} + +fn func2(_: Opt, _: Opt) { +} diff --git a/src/test/run-pass/default-ty-param-fallback/specialization_concrete.rs b/src/test/run-pass/default-ty-param-fallback/specialization_concrete.rs new file mode 100644 index 0000000000000..30a4eca18a776 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/specialization_concrete.rs @@ -0,0 +1,45 @@ +// 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(specialization)] + +use std::fmt::Debug; + +trait B { + fn b(&self) -> Self; +} + +default impl B for Option + where T: Default +{ + fn b(&self) -> Option { + Some(T::default()) + } +} + +impl B for Option +{ + fn b(&self) -> Option { + Some("special".into()) + } +} + +fn main() { + let x = None; + // Even with defaults, the concrete impl is prefered, + // the defaults are simply ignored. + foo(x.b()); +} + +fn foo(a: Option) + where T: Debug { + assert_eq!(format!("{:?}", a.unwrap()), "\"special\""); +} diff --git a/src/test/run-pass/default-ty-param-fallback/struct.rs b/src/test/run-pass/default-ty-param-fallback/struct.rs new file mode 100644 index 0000000000000..a54e5eb759adb --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/struct.rs @@ -0,0 +1,24 @@ +// 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::new(); + Foo::<_>::new(); +} diff --git a/src/test/run-pass/default-ty-param-fallback/trait_def_rules_over_impl.rs b/src/test/run-pass/default-ty-param-fallback/trait_def_rules_over_impl.rs new file mode 100644 index 0000000000000..4bcf7a1176848 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/trait_def_rules_over_impl.rs @@ -0,0 +1,31 @@ +// 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)] + +trait Bar { + // Current we consider only the default in the trait, + // never the one in the impl. + // Is this good? Is it bad? Is it just the way it works? + // If this is ok then we should forbid writing the default in the impl. + fn method(&self) -> A; +} + +struct Foo; + +impl Bar for Foo { + fn method(&self) -> A { + A::default() + } +} + +fn main() { + Foo.method(); +} diff --git a/src/test/run-pass/default-ty-param-fallback/trait_impl.rs b/src/test/run-pass/default-ty-param-fallback/trait_impl.rs new file mode 100644 index 0000000000000..085bd3f74a053 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/trait_impl.rs @@ -0,0 +1,39 @@ +// 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 Vac(Vec); + +impl Vac { + fn new() -> Self { + Vac(Vec::new()) + } +} + +trait Foo { } +trait Bar { } + +impl Foo for Vac {} +impl Bar for usize {} + +fn takes_foo(_: F) {} + +fn main() { + let x = Vac::new(); // x: Vac<$0> + // adds oblig Vac<$0> : Foo, + // and applies the default of `impl Vac` and + // `impl Foo for Vac`, which must agree. + // + // The default of F in takes_foo makes no difference here, + // because the corresponding inference var will be generalized + // to Vac<_>. + takes_foo(x); +} diff --git a/src/test/run-pass/default-ty-param-fallback/trait_impl_param_in_trait.rs b/src/test/run-pass/default-ty-param-fallback/trait_impl_param_in_trait.rs new file mode 100644 index 0000000000000..8c97370caa303 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/trait_impl_param_in_trait.rs @@ -0,0 +1,37 @@ +// 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)] + +trait B { + fn b(&self) -> T; +} + +impl B for X + where T: Default +{ + fn b(&self) -> T { + T::default() + } +} + +#[derive(Copy, Clone, Default)] +struct X(u8); + +fn main() { + let x = X(0); + let y = x.b(); + foo(y); + x.0; +} + +fn foo(a: T) -> T { + a +} diff --git a/src/test/run-pass/default-ty-param-fallback/trait_method_call_default_self.rs b/src/test/run-pass/default-ty-param-fallback/trait_method_call_default_self.rs new file mode 100644 index 0000000000000..19633ee5412cb --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/trait_method_call_default_self.rs @@ -0,0 +1,38 @@ +// 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; + +trait B { + fn b(&self) -> Self; +} + +// Strangely, having a default for `Self` +// will fail for fundamental types such as `T` or `Box`. +// Replace `Option` for `Box` in this test to reproduce. +impl B for Option + where T: Default +{ + fn b(&self) -> Option { + Some(T::default()) + } +} + +fn main() { + let x = None; + foo(x.b()); +} + +fn foo(a: Option) + where T: Debug + PartialEq<&'static str> { + assert_eq!(a.unwrap(), ""); +} diff --git a/src/test/run-pass/default-ty-param-fallback/type_alias.rs b/src/test/run-pass/default-ty-param-fallback/type_alias.rs new file mode 100644 index 0000000000000..78c0062c24451 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/type_alias.rs @@ -0,0 +1,25 @@ +// 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 HeshMep(Vec, Vec, S); + +impl HeshMep { + fn new() -> HeshMep { + HeshMep(Vec::new(), Vec::new(), S::default()) + } +} + +type IntMap = HeshMep; + +fn main() { + let _ = IntMap::new(); +} diff --git a/src/test/run-pass/default-ty-param-fallback/type_alias_see_through.rs b/src/test/run-pass/default-ty-param-fallback/type_alias_see_through.rs new file mode 100644 index 0000000000000..d25e3a2e8a217 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/type_alias_see_through.rs @@ -0,0 +1,23 @@ +// Copyright 2017 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)] + +type Strang = &'static str; + +fn main() { + let a = None; + func1(a); + func2(a); +} + +// Defaults on fns take precedence. +fn func1

(_: Option

) {} +fn func2

(_: Option

) {} diff --git a/src/test/compile-fail/auxiliary/default_ty_param_cross_crate_crate.rs b/src/test/ui/default-ty-param-fallback/auxiliary/default_ty_param_cross_crate_crate.rs similarity index 100% rename from src/test/compile-fail/auxiliary/default_ty_param_cross_crate_crate.rs rename to src/test/ui/default-ty-param-fallback/auxiliary/default_ty_param_cross_crate_crate.rs diff --git a/src/test/ui/default-ty-param-fallback/default_dependent_associated_type.rs b/src/test/ui/default-ty-param-fallback/default_dependent_associated_type.rs new file mode 100644 index 0000000000000..54541ac436175 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/default_dependent_associated_type.rs @@ -0,0 +1,36 @@ +// 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. +// compile-flags: --error-format=human + +#![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/ui/default-ty-param-fallback/default_dependent_associated_type.stderr b/src/test/ui/default-ty-param-fallback/default_dependent_associated_type.stderr new file mode 100644 index 0000000000000..e67f7aa8722a9 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/default_dependent_associated_type.stderr @@ -0,0 +1,10 @@ +error[E0283]: type annotations required: cannot resolve `_: std::default::Default` + --> $DIR/default_dependent_associated_type.rs:35:15 + | +35 | let foo = Foo::new(); + | ^^^^^^^^ + | + = note: required by `>::new` + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/dependent_defaults.rs b/src/test/ui/default-ty-param-fallback/dependent_defaults.rs new file mode 100644 index 0000000000000..40d9767239649 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/dependent_defaults.rs @@ -0,0 +1,19 @@ +// 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. +// compile-flags: --error-format=human + +#![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/ui/default-ty-param-fallback/dependent_defaults.stderr b/src/test/ui/default-ty-param-fallback/dependent_defaults.stderr new file mode 100644 index 0000000000000..1188d498ff40a --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/dependent_defaults.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/dependent_defaults.rs:18:15 + | +18 | let foo = Foo { t: 'a', data: PhantomData }; + | --- ^^^ cannot infer type for `U` + | | + | consider giving `foo` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/dont_skip_conflict.rs b/src/test/ui/default-ty-param-fallback/dont_skip_conflict.rs new file mode 100644 index 0000000000000..4bc3be2bda375 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/dont_skip_conflict.rs @@ -0,0 +1,34 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +use std::path::Path; +use std::mem::size_of; + +enum Opt { + Som(T), + Non, +} + +fn main() { + // func1 and func2 cannot agree so we fail. + // NB: While it would be future-proof wrt API evolution to use the `String` default in `Opt`, + // that is not future proof wrt to compiler evolution, + // such as making priority levels more fine-grained or just fixing bugs. + let x = Opt::Non; + func1(&x); + func2(&x); +} + +fn func1 = &'static str>(_: &Opt

) { } + +fn func2 = &'static &'static str>(_: &Opt

) { } diff --git a/src/test/ui/default-ty-param-fallback/dont_skip_conflict.stderr b/src/test/ui/default-ty-param-fallback/dont_skip_conflict.stderr new file mode 100644 index 0000000000000..fd4a1ed786eb9 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/dont_skip_conflict.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/dont_skip_conflict.rs:27:13 + | +27 | let x = Opt::Non; + | - ^^^^^^^^ cannot infer type for `T` + | | + | consider giving `x` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/elided_is_not_inferred.rs b/src/test/ui/default-ty-param-fallback/elided_is_not_inferred.rs new file mode 100644 index 0000000000000..7efcf64e9f807 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/elided_is_not_inferred.rs @@ -0,0 +1,30 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +struct Bar(T); + +impl Bar { + fn new() -> Bar { + Bar(Z::default()) + } +} + +fn main() { + let _:u32 = foo::(); + let _:Bar = Bar::new::(); +} + +fn foo() -> T { + T::default() +} + diff --git a/src/test/ui/default-ty-param-fallback/elided_is_not_inferred.stderr b/src/test/ui/default-ty-param-fallback/elided_is_not_inferred.stderr new file mode 100644 index 0000000000000..1bb7b710ddc7f --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/elided_is_not_inferred.stderr @@ -0,0 +1,26 @@ +error[E0412]: cannot find type `T` in this scope + --> $DIR/elided_is_not_inferred.rs:16:10 + | +16 | impl Bar { + | ^ not found in this scope + +error[E0308]: mismatched types + --> $DIR/elided_is_not_inferred.rs:23:17 + | +23 | let _:u32 = foo::(); + | ^^^^^^^^^^^^^^ expected u32, found struct `std::string::String` + | + = note: expected type `u32` + found type `std::string::String` + +error[E0308]: mismatched types + --> $DIR/elided_is_not_inferred.rs:24:22 + | +24 | let _:Bar = Bar::new::(); + | ^^^^^^^^^^^^^^^^^^^ expected u32, found struct `std::string::String` + | + = note: expected type `Bar` + found type `Bar` + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/default-ty-param-fallback/fallback_conflict.rs b/src/test/ui/default-ty-param-fallback/fallback_conflict.rs new file mode 100644 index 0000000000000..3a7b2f8026357 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/fallback_conflict.rs @@ -0,0 +1,24 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +use std::fmt::Debug; + +// Example from the RFC +fn foo() -> F { F::default() } + +fn bar(b: B) { println!("{:?}", b); } + +fn main() { + let x = foo(); + bar(x); +} diff --git a/src/test/ui/default-ty-param-fallback/fallback_conflict.stderr b/src/test/ui/default-ty-param-fallback/fallback_conflict.stderr new file mode 100644 index 0000000000000..bef89b2d19bf4 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/fallback_conflict.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/fallback_conflict.rs:22:9 + | +22 | let x = foo(); + | ^ + | | + | cannot infer type for `_` + | consider giving `x` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/fallback_conflict_cross_crate.rs b/src/test/ui/default-ty-param-fallback/fallback_conflict_cross_crate.rs new file mode 100644 index 0000000000000..794357162f6b4 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/fallback_conflict_cross_crate.rs @@ -0,0 +1,26 @@ +// 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 +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +extern crate default_param_test; + +use default_param_test::{Foo, bleh}; + +fn meh(x: Foo) {} + +fn main() { + let foo = bleh(); + + meh(foo); +} diff --git a/src/test/ui/default-ty-param-fallback/fallback_conflict_cross_crate.stderr b/src/test/ui/default-ty-param-fallback/fallback_conflict_cross_crate.stderr new file mode 100644 index 0000000000000..21bd5da3d2867 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/fallback_conflict_cross_crate.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/fallback_conflict_cross_crate.rs:23:15 + | +23 | let foo = bleh(); + | --- ^^^^ cannot infer type for `A` + | | + | consider giving `foo` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/feature_gate.rs b/src/test/ui/default-ty-param-fallback/feature_gate.rs new file mode 100644 index 0000000000000..36dea669fd877 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/feature_gate.rs @@ -0,0 +1,19 @@ +// 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. +// compile-flags: --error-format=human + +enum Opt { + Som(T), + Non, +} + +fn main() { + Opt::Non; +} diff --git a/src/test/ui/default-ty-param-fallback/feature_gate.stderr b/src/test/ui/default-ty-param-fallback/feature_gate.stderr new file mode 100644 index 0000000000000..af5fbe6d3891e --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/feature_gate.stderr @@ -0,0 +1,8 @@ +error[E0282]: type annotations needed + --> $DIR/feature_gate.rs:18:5 + | +18 | Opt::Non; + | ^^^^^^^^ cannot infer type for `T` + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/future_proof.rs b/src/test/ui/default-ty-param-fallback/future_proof.rs new file mode 100644 index 0000000000000..ca36877308694 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/future_proof.rs @@ -0,0 +1,28 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +use std::path::Path; + +fn func = String>(p: Option

) { + match p { + None => { println!("None"); } + Some(path) => { println!("{:?}", path.as_ref()); } + } +} + +fn main() { + // Dont fallback to future-proof against default on `noner`. + func(noner()); +} + +fn noner() -> Option { None } diff --git a/src/test/ui/default-ty-param-fallback/future_proof.stderr b/src/test/ui/default-ty-param-fallback/future_proof.stderr new file mode 100644 index 0000000000000..6160c569c6a10 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/future_proof.stderr @@ -0,0 +1,8 @@ +error[E0282]: type annotations needed + --> $DIR/future_proof.rs:25:5 + | +25 | func(noner()); + | ^^^^ cannot infer type for `P` + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/method_call_test.rs b/src/test/ui/default-ty-param-fallback/method_call_test.rs new file mode 100644 index 0000000000000..388997ee24b6f --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/method_call_test.rs @@ -0,0 +1,25 @@ +// 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. +// compile-flags: --error-format=human + +#![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/ui/default-ty-param-fallback/method_call_test.stderr b/src/test/ui/default-ty-param-fallback/method_call_test.stderr new file mode 100644 index 0000000000000..cbfe7c724d429 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/method_call_test.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/method_call_test.rs:23:9 + | +23 | let f = Foo.method(); + | ^ + | | + | cannot infer type for `_` + | consider giving `f` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/placeholder_type_hint.rs b/src/test/ui/default-ty-param-fallback/placeholder_type_hint.rs new file mode 100644 index 0000000000000..62e461291c6f1 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/placeholder_type_hint.rs @@ -0,0 +1,23 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +enum Opt { + Som(T), + Non, +} + +struct Foo(Opt); + +fn main() { + let _: Foo<_> = Foo(Opt::Non); +} diff --git a/src/test/ui/default-ty-param-fallback/placeholder_type_hint.stderr b/src/test/ui/default-ty-param-fallback/placeholder_type_hint.stderr new file mode 100644 index 0000000000000..c58f2fb42ff07 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/placeholder_type_hint.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/placeholder_type_hint.rs:22:21 + | +22 | let _: Foo<_> = Foo(Opt::Non); + | - ^^^ cannot infer type for `A` + | | + | consider giving the pattern a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/related_depent_defaults.rs b/src/test/ui/default-ty-param-fallback/related_depent_defaults.rs new file mode 100644 index 0000000000000..1aad506d6ec02 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/related_depent_defaults.rs @@ -0,0 +1,37 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +#[derive(Copy, Clone)] +enum Opt { + Som(T), + Non, +} + +fn main() { + let a = Opt::Non; + let b = Opt::Non; + func1(a, b); + func2(a, b); + + let c = Opt::Non; + let d = Opt::Non; + func1(c, d); + func2(d, c); +} + +fn func1(_: Opt, _: Opt) { +} + +fn func2(_: Opt, _: Opt) { +} + diff --git a/src/test/ui/default-ty-param-fallback/related_depent_defaults.stderr b/src/test/ui/default-ty-param-fallback/related_depent_defaults.stderr new file mode 100644 index 0000000000000..4915a1d04abf9 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/related_depent_defaults.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/related_depent_defaults.rs:21:13 + | +21 | let a = Opt::Non; + | - ^^^^^^^^ cannot infer type for `T` + | | + | consider giving `a` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/struct_and_type_alias.rs b/src/test/ui/default-ty-param-fallback/struct_and_type_alias.rs new file mode 100644 index 0000000000000..65b065c4a4775 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/struct_and_type_alias.rs @@ -0,0 +1,40 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +use std::marker::PhantomData; + +struct DeterministicHasher; +struct RandomHasher; + + +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/ui/default-ty-param-fallback/struct_and_type_alias.stderr b/src/test/ui/default-ty-param-fallback/struct_and_type_alias.stderr new file mode 100644 index 0000000000000..fd012aa11fe89 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/struct_and_type_alias.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/struct_and_type_alias.rs:38:20 + | +38 | let hash_map = mystd::HashMap::new(); + | -------- ^^^^^^^^^^^^^^^^^^^ cannot infer type for `H` + | | + | consider giving `hash_map` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/trait_impl.rs b/src/test/ui/default-ty-param-fallback/trait_impl.rs new file mode 100644 index 0000000000000..8f4c5046b672a --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_impl.rs @@ -0,0 +1,26 @@ +// 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. +// compile-flags: --error-format=human + +#![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/ui/default-ty-param-fallback/trait_impl.stderr b/src/test/ui/default-ty-param-fallback/trait_impl.stderr new file mode 100644 index 0000000000000..23acc0ea9f485 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_impl.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/trait_impl.rs:24:13 + | +24 | let x = Vec::new(); // x: Vec<$0> + | - ^^^^^^^^ cannot infer type for `T` + | | + | consider giving `x` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/trait_impl_param_in_trait.rs b/src/test/ui/default-ty-param-fallback/trait_impl_param_in_trait.rs new file mode 100644 index 0000000000000..5bf97859fb3c5 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_impl_param_in_trait.rs @@ -0,0 +1,37 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +trait B { + fn b(&self) -> T; +} + +impl B for X + where T: Default +{ + fn b(&self) -> T { + T::default() + } +} + +#[derive(Copy, Clone, Default)] +struct X(u8); + +fn main() { + let x = X(0); + let y = x.b(); + foo(y); +} + +fn foo(a: T) -> T { + a +} diff --git a/src/test/ui/default-ty-param-fallback/trait_impl_param_in_trait.stderr b/src/test/ui/default-ty-param-fallback/trait_impl_param_in_trait.stderr new file mode 100644 index 0000000000000..0445b1d30e6cc --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_impl_param_in_trait.stderr @@ -0,0 +1,11 @@ +error[E0282]: type annotations needed + --> $DIR/trait_impl_param_in_trait.rs:31:9 + | +31 | let y = x.b(); + | ^ + | | + | cannot infer type for `_` + | consider giving `y` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/trait_impl_simple.rs b/src/test/ui/default-ty-param-fallback/trait_impl_simple.rs new file mode 100644 index 0000000000000..e4e86182f4a8c --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_impl_simple.rs @@ -0,0 +1,27 @@ +// 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. +// compile-flags: --error-format=human + +#![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/ui/default-ty-param-fallback/trait_impl_simple.stderr b/src/test/ui/default-ty-param-fallback/trait_impl_simple.stderr new file mode 100644 index 0000000000000..63b6ee29923c8 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_impl_simple.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/trait_impl_simple.rs:25:13 + | +25 | let x = Vec::new(); // x: Vec<$0> + | - ^^^^^^^^ cannot infer type for `T` + | | + | consider giving `x` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/trait_method_call_default_self.rs b/src/test/ui/default-ty-param-fallback/trait_method_call_default_self.rs new file mode 100644 index 0000000000000..c5c59bc2bd02b --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_method_call_default_self.rs @@ -0,0 +1,36 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +use std::fmt::Debug; + +trait B { + fn b(&self) -> Self; +} + +impl B for Option + where T: Default +{ + fn b(&self) -> Option { + Some(T::default()) + } +} + +fn main() { + let x = None; + foo(x.b()); +} + +fn foo(a: Option) + where T: Debug + PartialEq<&'static str> { + assert_eq!(a.unwrap(), ""); +} diff --git a/src/test/ui/default-ty-param-fallback/trait_method_call_default_self.stderr b/src/test/ui/default-ty-param-fallback/trait_method_call_default_self.stderr new file mode 100644 index 0000000000000..2a43b061d7d33 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/trait_method_call_default_self.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/trait_method_call_default_self.rs:29:13 + | +29 | let x = None; + | - ^^^^ cannot infer type for `T` + | | + | consider giving `x` a type + +error: aborting due to previous error + diff --git a/src/test/ui/default-ty-param-fallback/type_alias.rs b/src/test/ui/default-ty-param-fallback/type_alias.rs new file mode 100644 index 0000000000000..43f811be5e815 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/type_alias.rs @@ -0,0 +1,20 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +use std::collections::HashMap; + +type IntMap = HashMap; + +fn main() { + let x = IntMap::new(); +} diff --git a/src/test/ui/default-ty-param-fallback/type_alias.stderr b/src/test/ui/default-ty-param-fallback/type_alias.stderr new file mode 100644 index 0000000000000..d7927ffc062d8 --- /dev/null +++ b/src/test/ui/default-ty-param-fallback/type_alias.stderr @@ -0,0 +1,10 @@ +error[E0282]: type annotations needed + --> $DIR/type_alias.rs:19:13 + | +19 | let x = IntMap::new(); + | - ^^^^^^^^^^^ cannot infer type for `K` + | | + | consider giving `x` a type + +error: aborting due to previous error +

(), size_of::<&str>()) +} diff --git a/src/test/run-pass/default-ty-param-fallback/fallback_in_impls.rs b/src/test/run-pass/default-ty-param-fallback/fallback_in_impls.rs new file mode 100644 index 0000000000000..d9ac51fc23b02 --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/fallback_in_impls.rs @@ -0,0 +1,23 @@ +// 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-fallback/fn_priority_over_ty_def.rs b/src/test/run-pass/default-ty-param-fallback/fn_priority_over_ty_def.rs new file mode 100644 index 0000000000000..1096c777c41ec --- /dev/null +++ b/src/test/run-pass/default-ty-param-fallback/fn_priority_over_ty_def.rs @@ -0,0 +1,32 @@ +// 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. +// compile-flags: --error-format=human + +#![feature(default_type_parameter_fallback)] + +use std::path::Path; + +enum Opt { + Som(T), + Non, +} + +fn main() { + // Defaults on the type definiton work, as long no other params are interfering. + let _ = Opt::Non; + let _: Opt<_> = Opt::Non; + + func1(None); + func2(Opt::Non); +} + +// Defaults on fns take precedence. +fn func1 = String>(p: Option