Address nits.
This commit is contained in:
parent
518ec1259a
commit
919975d0a5
@ -14,7 +14,6 @@ use middle::ty::{mod, AsPredicate, RegionEscape, Ty, ToPolyTraitRef};
|
||||
use std::collections::HashSet;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use syntax::ast;
|
||||
use util::common::ErrorReported;
|
||||
use util::ppaux::Repr;
|
||||
@ -102,26 +101,30 @@ impl<'tcx> FulfillmentContext<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn normalize_associated_type<'a>(&mut self,
|
||||
/// "Normalize" a projection type `<SomeType as SomeTrait>::X` by
|
||||
/// creating a fresh type variable `$0` as well as a projection
|
||||
/// predicate `<SomeType as SomeTrait>::X == $0`. When the
|
||||
/// inference engine runs, it will attempt to find an impl of
|
||||
/// `SomeTrait` or a where clause that lets us unify `$0` with
|
||||
/// something concrete. If this fails, we'll unify `$0` with
|
||||
/// `projection_ty` again.
|
||||
pub fn normalize_projection_type<'a>(&mut self,
|
||||
infcx: &InferCtxt<'a,'tcx>,
|
||||
trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||
item_name: ast::Name,
|
||||
projection_ty: ty::ProjectionTy<'tcx>,
|
||||
cause: ObligationCause<'tcx>)
|
||||
-> Ty<'tcx>
|
||||
{
|
||||
debug!("normalize_associated_type(trait_ref={}, item_name={})",
|
||||
trait_ref.repr(infcx.tcx),
|
||||
item_name.repr(infcx.tcx));
|
||||
debug!("normalize_associated_type(projection_ty={})",
|
||||
projection_ty.repr(infcx.tcx));
|
||||
|
||||
assert!(!trait_ref.has_escaping_regions());
|
||||
assert!(!projection_ty.has_escaping_regions());
|
||||
|
||||
// FIXME(#20304) -- cache
|
||||
|
||||
let ty_var = infcx.next_ty_var();
|
||||
let projection =
|
||||
ty::Binder(ty::ProjectionPredicate {
|
||||
projection_ty: ty::ProjectionTy { trait_ref: trait_ref,
|
||||
item_name: item_name },
|
||||
projection_ty: projection_ty,
|
||||
ty: ty_var
|
||||
});
|
||||
let obligation = Obligation::new(cause, projection.as_predicate());
|
||||
|
@ -117,7 +117,10 @@ pub enum ObligationCauseCode<'tcx> {
|
||||
|
||||
#[deriving(Clone)]
|
||||
pub struct DerivedObligationCause<'tcx> {
|
||||
/// Resolving this trait led to the current obligation
|
||||
/// The trait reference of the parent obligation that led to the
|
||||
/// current obligation. Note that only trait obligations lead to
|
||||
/// derived obligations, so we just store the trait reference here
|
||||
/// directly.
|
||||
parent_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
|
||||
/// The parent trait had this cause
|
||||
|
@ -20,7 +20,6 @@ use super::VtableImplData;
|
||||
use middle::infer;
|
||||
use middle::subst::Subst;
|
||||
use middle::ty::{mod, AsPredicate, ToPolyTraitRef, Ty};
|
||||
use std::fmt;
|
||||
use util::ppaux::Repr;
|
||||
|
||||
pub type PolyProjectionObligation<'tcx> =
|
||||
@ -34,10 +33,17 @@ pub type ProjectionTyObligation<'tcx> =
|
||||
|
||||
/// When attempting to resolve `<T as TraitRef>::Name == U`...
|
||||
pub enum ProjectionError<'tcx> {
|
||||
/// ...we could not find any helpful information on what `Name`
|
||||
/// might be. This could occur, for example, if there is a where
|
||||
/// clause `T : TraitRef` but not `T : TraitRef<Name=V>`. When
|
||||
/// normalizing, this case is where we opt to normalize back to
|
||||
/// the projection type `<T as TraitRef>::Name`.
|
||||
NoCandidate,
|
||||
|
||||
/// ...we found multiple sources of information and couldn't resolve the ambiguity.
|
||||
TooManyCandidates,
|
||||
|
||||
///
|
||||
/// ...`<T as TraitRef::Name>` ws resolved to some type `V` that failed to unify with `U`
|
||||
MismatchedTypes(MismatchedProjectionTypes<'tcx>),
|
||||
|
||||
/// ...an error occurred matching `T : TraitRef`
|
||||
@ -380,12 +386,6 @@ fn confirm_candidate<'cx,'tcx>(
|
||||
Ok(projected_ty)
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
self.err.repr(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for ProjectionError<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
match *self {
|
||||
@ -401,12 +401,6 @@ impl<'tcx> Repr<'tcx> for ProjectionError<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Show for super::MismatchedProjectionTypes<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "MismatchedProjectionTypes(..)")
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
match *self {
|
||||
|
@ -150,8 +150,15 @@ enum SelectionCandidate<'tcx> {
|
||||
}
|
||||
|
||||
struct SelectionCandidateSet<'tcx> {
|
||||
// a list of candidates that definitely apply to the current
|
||||
// obligation (meaning: types unify).
|
||||
vec: Vec<SelectionCandidate<'tcx>>,
|
||||
ambiguous: bool
|
||||
|
||||
// if this is true, then there were candidates that might or might
|
||||
// not have applied, but we couldn't tell. This occurs when some
|
||||
// of the input types are type variables, in which case there are
|
||||
// various "builtin" rules that might or might not trigger.
|
||||
ambiguous: bool,
|
||||
}
|
||||
|
||||
enum BuiltinBoundConditions<'tcx> {
|
||||
|
@ -385,9 +385,16 @@ impl<'tcx> fmt::Show for super::FulfillmentErrorCode<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> {
|
||||
impl<'tcx> Repr<'tcx> for super::MismatchedProjectionTypes<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
ty::type_err_to_str(tcx, self)
|
||||
self.err.repr(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> fmt::Show for super::MismatchedProjectionTypes<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "MismatchedProjectionTypes(..)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -1791,7 +1791,8 @@ pub enum Predicate<'tcx> {
|
||||
/// where T : 'a
|
||||
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
|
||||
|
||||
///
|
||||
/// where <T as TraitRef>::Name == X, approximately.
|
||||
/// See `ProjectionPredicate` struct for details.
|
||||
Projection(PolyProjectionPredicate<'tcx>),
|
||||
}
|
||||
|
||||
@ -1857,9 +1858,14 @@ impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the projection of an associated type. In explicit UFCS
|
||||
/// form this would be written `<T as Trait<..>>::N`.
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||
pub struct ProjectionTy<'tcx> {
|
||||
/// The trait reference `T as Trait<..>`.
|
||||
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||
|
||||
/// The name `N` of the associated type.
|
||||
pub item_name: ast::Name,
|
||||
}
|
||||
|
||||
@ -2179,6 +2185,12 @@ impl<'tcx> ParameterEnvironment<'tcx> {
|
||||
/// - `generics`: the set of type parameters and their bounds
|
||||
/// - `ty`: the base types, which may reference the parameters defined
|
||||
/// in `generics`
|
||||
///
|
||||
/// Note that TypeSchemes are also sometimes called "polytypes" (and
|
||||
/// in fact this struct used to carry that name, so you may find some
|
||||
/// stray references in a comment or something). We try to reserve the
|
||||
/// "poly" prefix to refer to higher-ranked things, as in
|
||||
/// `PolyTraitRef`.
|
||||
#[deriving(Clone, Show)]
|
||||
pub struct TypeScheme<'tcx> {
|
||||
pub generics: Generics<'tcx>,
|
||||
@ -4680,6 +4692,12 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Repr<'tcx> for ty::type_err<'tcx> {
|
||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||
ty::type_err_to_str(tcx, self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Explains the source of a type err in a short, human readable way. This is meant to be placed
|
||||
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
|
||||
/// afterwards to present additional details, particularly when it comes to lifetime-related
|
||||
|
@ -244,7 +244,6 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
decl_def_id: ast::DefId,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
path: &ast::Path)
|
||||
-> Substs<'tcx>
|
||||
@ -280,7 +279,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||
create_substs_for_ast_path(this,
|
||||
rscope,
|
||||
path.span,
|
||||
decl_def_id,
|
||||
decl_generics,
|
||||
None,
|
||||
types,
|
||||
@ -291,7 +289,6 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||
this: &AC,
|
||||
rscope: &RS,
|
||||
span: Span,
|
||||
_decl_def_id: ast::DefId,
|
||||
decl_generics: &ty::Generics<'tcx>,
|
||||
self_ty: Option<Ty<'tcx>>,
|
||||
types: Vec<Ty<'tcx>>,
|
||||
@ -621,7 +618,6 @@ fn ast_path_to_trait_ref<'a,'tcx,AC,RS>(
|
||||
let substs = create_substs_for_ast_path(this,
|
||||
&shifted_rscope,
|
||||
path.span,
|
||||
trait_def_id,
|
||||
&trait_def.generics,
|
||||
self_ty,
|
||||
types,
|
||||
@ -705,7 +701,6 @@ pub fn ast_path_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
|
||||
|
||||
let substs = ast_path_substs_for_ty(this,
|
||||
rscope,
|
||||
did,
|
||||
&generics,
|
||||
path);
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
@ -747,7 +742,7 @@ pub fn ast_path_to_ty_relaxed<'tcx,AC,RS>(
|
||||
Substs::new(VecPerParamSpace::params_from_type(type_params),
|
||||
VecPerParamSpace::params_from_type(region_params))
|
||||
} else {
|
||||
ast_path_substs_for_ty(this, rscope, did, &generics, path)
|
||||
ast_path_substs_for_ty(this, rscope, &generics, path)
|
||||
};
|
||||
|
||||
let ty = decl_ty.subst(tcx, &substs);
|
||||
|
@ -80,11 +80,9 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> {
|
||||
self.span,
|
||||
self.body_id,
|
||||
ObligationCauseCode::MiscObligation);
|
||||
let trait_ref = data.trait_ref.clone();
|
||||
self.fulfillment_cx
|
||||
.normalize_associated_type(self.infcx,
|
||||
trait_ref,
|
||||
data.item_name,
|
||||
.normalize_projection_type(self.infcx,
|
||||
data.clone(),
|
||||
cause)
|
||||
}
|
||||
_ => {
|
||||
|
@ -1758,9 +1758,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
traits::ObligationCauseCode::MiscObligation);
|
||||
self.inh.fulfillment_cx
|
||||
.borrow_mut()
|
||||
.normalize_associated_type(self.infcx(),
|
||||
trait_ref,
|
||||
item_name,
|
||||
.normalize_projection_type(self.infcx(),
|
||||
ty::ProjectionTy {
|
||||
trait_ref: trait_ref,
|
||||
item_name: item_name,
|
||||
},
|
||||
cause)
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,9 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// Helper for test issue-18048, which tests associated types in a
|
||||
// cross-crate scenario.
|
||||
|
||||
#![crate_type="lib"]
|
||||
#![feature(associated_types)]
|
||||
|
@ -8,14 +8,14 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// aux-build:issue-18048-lib.rs
|
||||
// aux-build:associated-types-cc-lib.rs
|
||||
|
||||
// Test that we are able to reference cross-crate traits that employ
|
||||
// associated types.
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
extern crate "issue-18048-lib" as bar;
|
||||
extern crate "associated-types-cc-lib" as bar;
|
||||
|
||||
use bar::Bar;
|
||||
|
@ -8,7 +8,7 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// ignore-pretty -- currently pretty prints as `Hash<<Self as Hasher...` which fails to parse
|
||||
// ignore-pretty -- FIXME(#17362) pretty prints as `Hash<<Self as Hasher...` which fails to parse
|
||||
|
||||
#![feature(associated_types)]
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user