From 265a1e4c9cd57bd10251e39c1a18f4f5863c9db3 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sat, 14 Feb 2015 22:50:12 +0800 Subject: [PATCH 1/5] Loose some dead code --- src/librustc/middle/ty.rs | 13 ------------- src/librustc/middle/ty_fold.rs | 12 ------------ 2 files changed, 25 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 1206424550f95..ef788ee4f9067 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -5116,19 +5116,6 @@ pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool { }) } -/// Returns the parameter index that the given associated type corresponds to. -pub fn associated_type_parameter_index(cx: &ctxt, - trait_def: &TraitDef, - associated_type_id: ast::DefId) - -> uint { - for type_parameter_def in trait_def.generics.types.iter() { - if type_parameter_def.def_id == associated_type_id { - return type_parameter_def.index as uint - } - } - cx.sess.bug("couldn't find associated type parameter index") -} - pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId) -> Rc> { lookup_locally_or_in_crate_store("trait_item_def_ids", diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 5e46ce08e4f76..ada0de16ffb49 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -575,18 +575,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::ClosureUpvar<'tcx> { } } -impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a { - fn fold_with>(&self, folder: &mut F) -> ty::ParameterEnvironment<'a, 'tcx> { - ty::ParameterEnvironment { - tcx: self.tcx, - free_substs: self.free_substs.fold_with(folder), - implicit_region_bound: self.implicit_region_bound.fold_with(folder), - caller_bounds: self.caller_bounds.fold_with(folder), - selection_cache: traits::SelectionCache::new(), - } - } -} - /////////////////////////////////////////////////////////////////////////// // "super" routines: these are the default implementations for TypeFolder. // From bb07d4a663420faf21caceba7167205e69ca3094 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sat, 14 Feb 2015 23:25:31 +0800 Subject: [PATCH 2/5] Refactor compare_impl_method a bit --- src/librustc/middle/subst.rs | 6 +++++ src/librustc_typeck/check/compare_method.rs | 27 +++++---------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 684b28d03739e..b5d19a66f322a 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -157,6 +157,12 @@ impl<'tcx> Substs<'tcx> { |r, m_regions| r.with_vec(FnSpace, m_regions)); Substs { types: types, regions: regions } } + + pub fn with_method_from(self, other: &Substs<'tcx>) -> Substs<'tcx> { + let types = other.types.get_slice(FnSpace).to_vec(); + let regions = other.regions().get_slice(FnSpace).to_vec(); + self.with_method(types, regions) + } } impl RegionSubsts { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index 1e1d7e0926038..598c44261b187 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -40,9 +40,6 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, debug!("compare_impl_method(impl_trait_ref={})", impl_trait_ref.repr(tcx)); - debug!("compare_impl_method: impl_trait_ref (liberated) = {}", - impl_trait_ref.repr(tcx)); - let infcx = infer::new_infer_ctxt(tcx); let mut fulfillment_cx = traits::FulfillmentContext::new(); @@ -180,10 +177,8 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // Create mapping from trait to skolemized. let trait_to_skol_substs = - trait_to_impl_substs - .subst(tcx, impl_to_skol_substs) - .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(), - impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec()); + trait_to_impl_substs.subst(tcx, impl_to_skol_substs) + .with_method_from(impl_to_skol_substs); debug!("compare_impl_method: trait_to_skol_substs={}", trait_to_skol_substs.repr(tcx)); @@ -208,10 +203,9 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, impl_m.predicates.instantiate(tcx, impl_to_skol_substs); let (impl_bounds, _) = - infcx.replace_late_bound_regions_with_fresh_var( - impl_m_span, - infer::HigherRankedType, - &ty::Binder(impl_bounds)); + infcx.replace_late_bound_regions_with_fresh_var(impl_m_span, + infer::HigherRankedType, + &ty::Binder(impl_bounds)); debug!("compare_impl_method: impl_bounds={}", impl_bounds.repr(tcx)); @@ -243,7 +237,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, let trait_param_env = traits::normalize_param_env_or_error(trait_param_env, normalize_cause.clone()); - debug!("compare_impl_method: trait_bounds={}", + debug!("compare_impl_method: trait_param_env.caller_bounds={}", trait_param_env.caller_bounds.repr(tcx)); let mut selcx = traits::SelectionContext::new(&infcx, &trait_param_env); @@ -276,12 +270,6 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, // any associated types appearing in the fn arguments or return // type. - // Compute skolemized form of impl and trait method tys. - let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone())); - let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs); - let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone())); - let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs); - let err = infcx.try(|snapshot| { let origin = infer::MethodCompatCheck(impl_m_span); @@ -336,9 +324,6 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>, match err { Ok(()) => { } Err(terr) => { - debug!("checking trait method for compatibility: impl ty {}, trait ty {}", - impl_fty.repr(tcx), - trait_fty.repr(tcx)); span_err!(tcx.sess, impl_m_span, E0053, "method `{}` has an incompatible type for trait: {}", token::get_name(trait_m.name), From a87e37d4100ff680c8083981ce8cd7767a836679 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sun, 22 Feb 2015 17:15:19 +0800 Subject: [PATCH 3/5] No need to be public --- src/librustc/middle/ty.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index ef788ee4f9067..7cfa535084532 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -4295,8 +4295,8 @@ pub fn ty_region(tcx: &ctxt, } } -pub fn free_region_from_def(outlives_extent: region::DestructionScopeData, - def: &RegionParameterDef) +fn free_region_from_def(outlives_extent: region::DestructionScopeData, + def: &RegionParameterDef) -> ty::Region { let ret = @@ -6342,7 +6342,7 @@ pub fn construct_free_substs<'a,'tcx>( region_params: &[RegionParameterDef]) { for r in region_params { - regions.push(r.space, ty::free_region_from_def(all_outlive_extent, r)); + regions.push(r.space, free_region_from_def(all_outlive_extent, r)); } } From 8303441648b3c8b54703f578c28d001fffdc0045 Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sat, 21 Feb 2015 00:28:05 +0800 Subject: [PATCH 4/5] Normalize parameter environment with its own substitution Otherwise, the substitution is carried out from outside perspective, which would be against the very purpose of `ParameterEnvironment`. Closes #21750 Closes #22077 --- src/librustc/middle/traits/mod.rs | 8 ++-- src/librustc/middle/traits/project.rs | 54 ++++++++++++++------------- src/librustc/middle/traits/select.rs | 21 ++++++++++- src/librustc/middle/ty.rs | 17 ++++++++- src/librustc_typeck/check/assoc.rs | 3 +- src/librustc_typeck/check/wf.rs | 1 + src/test/compile-fail/issue-22077.rs | 26 +++++++++++++ src/test/run-pass/issue-21750.rs | 36 ++++++++++++++++++ 8 files changed, 133 insertions(+), 33 deletions(-) create mode 100644 src/test/compile-fail/issue-22077.rs create mode 100644 src/test/run-pass/issue-21750.rs diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index a63dcfc24a10e..cf81af31bd519 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -413,10 +413,10 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi } } -pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>, - cause: ObligationCause<'tcx>) - -> Result, - Vec>> +fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>, + cause: ObligationCause<'tcx>) + -> Result, + Vec>> { let tcx = param_env.tcx; diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index 13f309e129ac9..c4143a858ff43 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -21,7 +21,7 @@ use super::VtableImplData; use super::util; use middle::infer; -use middle::subst::{Subst, Substs}; +use middle::subst::Substs; use middle::ty::{self, AsPredicate, ReferencesError, RegionEscape, HasProjectionTypes, ToPolyTraitRef, Ty}; use middle::ty_fold::{self, TypeFoldable, TypeFolder}; @@ -849,36 +849,38 @@ fn confirm_impl_candidate<'cx,'tcx>( impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>) -> (Ty<'tcx>, Vec>) { + let tcx = selcx.tcx(); // there don't seem to be nicer accessors to these: - let impl_items_map = selcx.tcx().impl_items.borrow(); - let impl_or_trait_items_map = selcx.tcx().impl_or_trait_items.borrow(); + let impl_items_map = tcx.impl_items.borrow(); + let impl_or_trait_items_map = tcx.impl_or_trait_items.borrow(); let impl_items = &impl_items_map[impl_vtable.impl_def_id]; - let mut impl_ty = None; - for impl_item in impl_items { - let assoc_type = match impl_or_trait_items_map[impl_item.def_id()] { - ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(), - ty::MethodTraitItem(..) => { continue; } - }; - - if assoc_type.name != obligation.predicate.item_name { - continue; - } - - let impl_poly_ty = ty::lookup_item_type(selcx.tcx(), assoc_type.def_id); - impl_ty = Some(impl_poly_ty.ty.subst(selcx.tcx(), &impl_vtable.substs)); - break; - } + let assoc_type = + impl_items + .iter() + .filter_map(|item| { + match impl_or_trait_items_map[item.def_id()] { + ty::TypeTraitItem(ref assoc_type) + if assoc_type.name == obligation.predicate.item_name => { + Some(assoc_type) + } + _ => None + } + }) + .next(); - match impl_ty { - Some(ty) => (ty, impl_vtable.nested.into_vec()), + match assoc_type { + Some(assoc_type) => { + let impl_ty = selcx.instantiate_assoc_type(assoc_type, + &impl_vtable.substs); + (impl_ty, impl_vtable.nested.into_vec()) + }, None => { - // This means that the impl is missing a - // definition for the associated type. This error - // ought to be reported by the type checker method - // `check_impl_items_against_trait`, so here we - // just return ty_err. - (selcx.tcx().types.err, vec!()) + // This means that the impl is missing a definition for the + // associated type. This error ought to be reported by the + // type checker method `check_impl_items_against_trait`, so + // here we just return ty_err. + (tcx.types.err, vec![]) } } } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 085758b44b5c7..771e8da5efd7f 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -33,7 +33,7 @@ use super::{util}; use middle::fast_reject; use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace}; -use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty}; +use middle::ty::{self, AssociatedType, RegionEscape, ToPolyTraitRef, Ty}; use middle::infer; use middle::infer::{InferCtxt, TypeFreshener}; use middle::ty_fold::TypeFoldable; @@ -2195,6 +2195,25 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /////////////////////////////////////////////////////////////////////////// // Miscellany + pub fn instantiate_assoc_type(&self, + assoc_ty: &AssociatedType, + impl_substs: &Substs<'tcx>) + -> Ty<'tcx> + { + let poly_ty = ty::lookup_item_type(self.tcx(), assoc_ty.def_id); + let substs = + if self.param_env().def_id == assoc_ty.container.id() { + // If the associated type we are about to instantiate is + // defined in the item current parameter environment is + // associated with, we are obliged to use free substitutions. + &self.param_env().free_substs + } else { + impl_substs + }; + + poly_ty.ty.subst(self.tcx(), substs) + } + fn push_stack<'o,'s:'o>(&mut self, previous_stack: Option<&'s TraitObligationStack<'s, 'tcx>>, obligation: &'o TraitObligation<'tcx>) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 7cfa535084532..b45a31a159892 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -80,7 +80,7 @@ use std::vec::{CowVec, IntoIter}; use collections::enum_set::{EnumSet, CLike}; use std::collections::{HashMap, HashSet}; use syntax::abi; -use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, LOCAL_CRATE}; +use syntax::ast::{CrateNum, DefId, Ident, ItemTrait, DUMMY_NODE_ID, LOCAL_CRATE}; use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility}; use syntax::ast_util::{self, is_local, lit_is_str, local_def, PostExpansionMethod}; @@ -2135,6 +2135,13 @@ impl<'tcx> TraitRef<'tcx> { pub struct ParameterEnvironment<'a, 'tcx:'a> { pub tcx: &'a ctxt<'tcx>, + /// Item the parameter environment is associated with. For `ItemImpl` or + /// `ItemFn`, this is the item itself; for `MethodImplItem`, however, this + /// is the implementation (container) it is in. A certain method may make + /// use of associated types, which are at the container level. So we need + /// to know this when instantiating associated types for methods. + pub def_id: DefId, + /// See `construct_free_substs` for details. pub free_substs: Substs<'tcx>, @@ -2161,6 +2168,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { { ParameterEnvironment { tcx: self.tcx, + def_id: self.def_id, free_substs: self.free_substs.clone(), implicit_region_bound: self.implicit_region_bound, caller_bounds: caller_bounds, @@ -2180,6 +2188,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let method_bounds = &method_ty.predicates; construct_parameter_environment( cx, + method_ty.container.id(), method.span, method_generics, method_bounds, @@ -2217,6 +2226,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let method_bounds = &method_ty.predicates; construct_parameter_environment( cx, + method_ty.container.id(), method.span, method_generics, method_bounds, @@ -2246,6 +2256,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let fn_predicates = lookup_predicates(cx, fn_def_id); construct_parameter_environment(cx, + fn_def_id, item.span, &fn_scheme.generics, &fn_predicates, @@ -2260,6 +2271,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { let scheme = lookup_item_type(cx, def_id); let predicates = lookup_predicates(cx, def_id); construct_parameter_environment(cx, + def_id, item.span, &scheme.generics, &predicates, @@ -6305,6 +6317,7 @@ impl Variance { /// are no free type/lifetime parameters in scope. pub fn empty_parameter_environment<'a,'tcx>(cx: &'a ctxt<'tcx>) -> ParameterEnvironment<'a,'tcx> { ty::ParameterEnvironment { tcx: cx, + def_id: local_def(DUMMY_NODE_ID), free_substs: Substs::empty(), caller_bounds: Vec::new(), implicit_region_bound: ty::ReEmpty, @@ -6361,6 +6374,7 @@ pub fn construct_free_substs<'a,'tcx>( /// See `ParameterEnvironment` struct def'n for details pub fn construct_parameter_environment<'a,'tcx>( tcx: &'a ctxt<'tcx>, + def_id: DefId, span: Span, generics: &ty::Generics<'tcx>, generic_predicates: &ty::GenericPredicates<'tcx>, @@ -6411,6 +6425,7 @@ pub fn construct_parameter_environment<'a,'tcx>( let unnormalized_env = ty::ParameterEnvironment { tcx: tcx, + def_id: def_id, free_substs: free_substs, implicit_region_bound: ty::ReScope(free_id_outlive.to_code_extent()), caller_bounds: predicates, diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs index 377af080526b7..ee4676b8d25fa 100644 --- a/src/librustc_typeck/check/assoc.rs +++ b/src/librustc_typeck/check/assoc.rs @@ -29,7 +29,8 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>, debug!("normalize_associated_types_in(value={})", value.repr(infcx.tcx)); let mut selcx = SelectionContext::new(infcx, typer); let cause = ObligationCause::new(span, body_id, MiscObligation); - let Normalized { value: result, obligations } = traits::normalize(&mut selcx, cause, value); + let Normalized { value: result, + obligations } = traits::normalize(&mut selcx, cause, value); debug!("normalize_associated_types_in: result={} predicates={}", result.repr(infcx.tcx), obligations.repr(infcx.tcx)); diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index b0ded25af1700..db16a29bab8e8 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -139,6 +139,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> { reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates); let param_env = ty::construct_parameter_environment(ccx.tcx, + item_def_id, item.span, &type_scheme.generics, &type_predicates, diff --git a/src/test/compile-fail/issue-22077.rs b/src/test/compile-fail/issue-22077.rs new file mode 100644 index 0000000000000..9992068e67f1a --- /dev/null +++ b/src/test/compile-fail/issue-22077.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. + +trait Fun { + type Output; + fn call<'x>(&'x self) -> Self::Output; +} + +struct Holder { x: String } + +impl<'a> Fun for Holder { + type Output = &'a str; + fn call<'b>(&'b self) -> &'b str { + //~^ ERROR method `call` has an incompatible type for trait + &self.x[..] + } +} + +fn main() {} diff --git a/src/test/run-pass/issue-21750.rs b/src/test/run-pass/issue-21750.rs new file mode 100644 index 0000000000000..7c039a14f4801 --- /dev/null +++ b/src/test/run-pass/issue-21750.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. + +pub trait Arg { + fn arg(&self) -> A; +} + +pub trait Traversal { + type Item; + fn foreach>(F); +} + +impl<'a> Traversal for i32 { + type Item = &'a i32; + fn foreach>(f: F) { + f.arg(); + } +} + +impl<'a> Traversal for u8 { + type Item = &'a u8; + // A more verbose way to refer to the associated type. Should also work + // nonetheless. + fn foreach::Item>>(f: F) { + let _ = f.arg(); + } +} + +fn main() {} From 73bd5cfc5394d472050ac4f9f000079fcd077afb Mon Sep 17 00:00:00 2001 From: Edward Wang Date: Sun, 22 Feb 2015 18:34:07 +0800 Subject: [PATCH 5/5] Also fix #22066 --- src/librustc/middle/traits/project.rs | 3 +- src/librustc/middle/traits/select.rs | 39 +++++++++++++------ ...ssoc-type-region-bound-in-trait-not-met.rs | 4 +- ...ssoc-type-static-bound-in-trait-not-met.rs | 2 +- src/test/run-pass/issue-22066.rs | 22 +++++++++++ 5 files changed, 53 insertions(+), 17 deletions(-) create mode 100644 src/test/run-pass/issue-22066.rs diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index c4143a858ff43..9c8141817c40a 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -561,8 +561,7 @@ fn assemble_candidates_from_trait_def<'cx,'tcx>( }; // If so, extract what we know from the trait and try to come up with a good answer. - let trait_predicates = ty::lookup_predicates(selcx.tcx(), trait_ref.def_id); - let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs); + let bounds = selcx.instantiate_trait_predicates(&trait_ref); assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref, candidate_set, bounds.predicates.into_vec()); } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 771e8da5efd7f..165ad5955a3e8 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -33,14 +33,15 @@ use super::{util}; use middle::fast_reject; use middle::subst::{Subst, Substs, TypeSpace, VecPerParamSpace}; -use middle::ty::{self, AssociatedType, RegionEscape, ToPolyTraitRef, Ty}; +use middle::ty::{self, AssociatedType, RegionEscape, ToPolyTraitRef, TraitRef, Ty}; use middle::infer; use middle::infer::{InferCtxt, TypeFreshener}; use middle::ty_fold::TypeFoldable; use std::cell::RefCell; use std::collections::hash_map::HashMap; use std::rc::Rc; -use syntax::{abi, ast}; +use syntax::abi; +use syntax::ast::{self, DefId}; use util::common::ErrorReported; use util::ppaux::Repr; @@ -2201,19 +2202,33 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { -> Ty<'tcx> { let poly_ty = ty::lookup_item_type(self.tcx(), assoc_ty.def_id); - let substs = - if self.param_env().def_id == assoc_ty.container.id() { - // If the associated type we are about to instantiate is - // defined in the item current parameter environment is - // associated with, we are obliged to use free substitutions. - &self.param_env().free_substs - } else { - impl_substs - }; - + let substs = self.maybe_pick_free_substs(assoc_ty.container.id(), impl_substs); poly_ty.ty.subst(self.tcx(), substs) } + pub fn instantiate_trait_predicates(&self, + trait_ref: &Rc>) + -> ty::InstantiatedPredicates<'tcx> + { + let trait_predicates = ty::lookup_predicates(self.tcx(), trait_ref.def_id); + let substs = self.maybe_pick_free_substs(trait_ref.def_id, trait_ref.substs); + trait_predicates.instantiate(self.tcx(), substs) + } + + fn maybe_pick_free_substs(&self, + target_def_id: DefId, + substs: &'cx Substs<'tcx>) + -> &'cx Substs<'tcx> + { + // The free substitutions take precedence over the given one if + // current parameter environment is associated with `target_def_id`. + if self.param_env().def_id == target_def_id { + &self.param_env().free_substs + } else { + substs + } + } + fn push_stack<'o,'s:'o>(&mut self, previous_stack: Option<&'s TraitObligationStack<'s, 'tcx>>, obligation: &'o TraitObligation<'tcx>) diff --git a/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs index f921eccef1f8c..f1ed7b6e33dbf 100644 --- a/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs +++ b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -22,12 +22,12 @@ impl<'a> Foo<'a> for &'a i16 { } impl<'a> Foo<'static> for &'a i32 { - //~^ ERROR cannot infer + //~^ ERROR does not fulfill the required lifetime type Value = &'a i32; } impl<'a,'b> Foo<'b> for &'a i64 { - //~^ ERROR cannot infer + //~^ ERROR does not fulfill the required lifetime type Value = &'a i32; } diff --git a/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs index 1cf83b8ac585f..7c371e3c15355 100644 --- a/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs +++ b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -17,7 +17,7 @@ trait Foo { } impl<'a> Foo for &'a i32 { - //~^ ERROR cannot infer + //~^ ERROR does not fulfill the required lifetime type Value = &'a i32; } diff --git a/src/test/run-pass/issue-22066.rs b/src/test/run-pass/issue-22066.rs new file mode 100644 index 0000000000000..2efcfc3a756e4 --- /dev/null +++ b/src/test/run-pass/issue-22066.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. + +pub trait LineFormatter<'a> { + type Iter: Iterator + 'a; + fn iter(&'a self, line: &'a str) -> Self::Iter; + + fn dimensions(&'a self, line: &'a str) { + for grapheme in self.iter(line) { + let _ = grapheme.len(); + } + } +} + +fn main() {}