diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c448af2288a65cb37a72121d194879f1c8c9b8c4..d516c648d7ed81101c905502a25d81498844ba8d 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -60,7 +60,7 @@ use middle::ty::{self, RegionEscape, Ty, ToPredicate, HasTypeFlags}; use middle::ty_fold; use require_c_abi_if_variadic; -use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ExplicitRscope, +use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope, ElisionFailureInfo, ElidedLifetime}; use util::common::{ErrorReported, FN_OUTPUT_NAME}; @@ -1208,40 +1208,33 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>, (_, def::DefSelfTy(Some(trait_did), Some((impl_id, _)))) => { // `Self` in an impl of a trait - we have a concrete self type and a // trait reference. - match tcx.map.expect_item(impl_id).node { - ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) => { - if this.ensure_super_predicates(span, trait_did).is_err() { - return (tcx.types.err, ty_path_def); - } + let trait_ref = tcx.impl_trait_ref(ast_util::local_def(impl_id)).unwrap(); + let trait_ref = if let Some(free_substs) = this.get_free_substs() { + trait_ref.subst(tcx, free_substs) + } else { + trait_ref + }; - let trait_segment = &trait_ref.path.segments.last().unwrap(); - let trait_ref = ast_path_to_mono_trait_ref(this, - &ExplicitRscope, - span, - PathParamMode::Explicit, - trait_did, - Some(ty), - trait_segment); - - let candidates: Vec = - traits::supertraits(tcx, ty::Binder(trait_ref.clone())) - .filter(|r| this.trait_defines_associated_type_named(r.def_id(), - assoc_name)) - .collect(); - - match one_bound_for_assoc_type(tcx, - candidates, - "Self", - &token::get_name(assoc_name), - span) { - Ok(bound) => bound, - Err(ErrorReported) => return (tcx.types.err, ty_path_def), - } - } - _ => unreachable!() + if this.ensure_super_predicates(span, trait_did).is_err() { + return (tcx.types.err, ty_path_def); + } + + let candidates: Vec = + traits::supertraits(tcx, ty::Binder(trait_ref)) + .filter(|r| this.trait_defines_associated_type_named(r.def_id(), + assoc_name)) + .collect(); + + match one_bound_for_assoc_type(tcx, + candidates, + "Self", + &token::get_name(assoc_name), + span) { + Ok(bound) => bound, + Err(ErrorReported) => return (tcx.types.err, ty_path_def), } } - (&ty::TyParam(_), def::DefSelfTy(Some(trait_did), None)) => { + (&ty::TyParam(_), def::DefSelfTy(Some(trait_did), None)) => { assert_eq!(trait_did.krate, ast::LOCAL_CRATE); match find_bound_for_assoc_item(this, trait_did.node, diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 5a6519cb4b7a2e5e0b91fe626f93b5cef89a528a..b003f0fc4f8a6a9335fc81105566a7d43ac9ee19 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -836,6 +836,18 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { ty: selfty }); tcx.predicates.borrow_mut().insert(local_def(it.id), ty_predicates.clone()); + if let &Some(ref ast_trait_ref) = opt_trait_ref { + tcx.impl_trait_refs.borrow_mut().insert( + local_def(it.id), + Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), + &ExplicitRscope, + ast_trait_ref, + Some(selfty))) + ); + } else { + tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), None); + } + // If there is a trait reference, treat the methods as always public. // This is to work around some incorrect behavior in privacy checking: @@ -935,18 +947,6 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) { } } - if let &Some(ref ast_trait_ref) = opt_trait_ref { - tcx.impl_trait_refs.borrow_mut().insert( - local_def(it.id), - Some(astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates), - &ExplicitRscope, - ast_trait_ref, - Some(selfty))) - ); - } else { - tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), None); - } - enforce_impl_params_are_constrained(tcx, generics, local_def(it.id), diff --git a/src/test/run-pass/issue-27281.rs b/src/test/run-pass/issue-27281.rs new file mode 100644 index 0000000000000000000000000000000000000000..c84fc0fffe32f086a7df569de904ce21b0a2d527 --- /dev/null +++ b/src/test/run-pass/issue-27281.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. + +pub trait Trait<'a> { + type T; + type U; + fn foo(&self, s: &'a ()) -> &'a (); +} + +impl<'a> Trait<'a> for () { + type T = &'a (); + type U = Self::T; + + fn foo(&self, s: &'a ()) -> &'a () { + let t: Self::T = s; t + } +} + +fn main() {}