Address nits.
This commit is contained in:
parent
518ec1259a
commit
919975d0a5
12 changed files with 75 additions and 45 deletions
|
@ -14,7 +14,6 @@ use middle::ty::{mod, AsPredicate, RegionEscape, Ty, ToPolyTraitRef};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::rc::Rc;
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use util::common::ErrorReported;
|
use util::common::ErrorReported;
|
||||||
use util::ppaux::Repr;
|
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>,
|
infcx: &InferCtxt<'a,'tcx>,
|
||||||
trait_ref: Rc<ty::TraitRef<'tcx>>,
|
projection_ty: ty::ProjectionTy<'tcx>,
|
||||||
item_name: ast::Name,
|
|
||||||
cause: ObligationCause<'tcx>)
|
cause: ObligationCause<'tcx>)
|
||||||
-> Ty<'tcx>
|
-> Ty<'tcx>
|
||||||
{
|
{
|
||||||
debug!("normalize_associated_type(trait_ref={}, item_name={})",
|
debug!("normalize_associated_type(projection_ty={})",
|
||||||
trait_ref.repr(infcx.tcx),
|
projection_ty.repr(infcx.tcx));
|
||||||
item_name.repr(infcx.tcx));
|
|
||||||
|
|
||||||
assert!(!trait_ref.has_escaping_regions());
|
assert!(!projection_ty.has_escaping_regions());
|
||||||
|
|
||||||
// FIXME(#20304) -- cache
|
// FIXME(#20304) -- cache
|
||||||
|
|
||||||
let ty_var = infcx.next_ty_var();
|
let ty_var = infcx.next_ty_var();
|
||||||
let projection =
|
let projection =
|
||||||
ty::Binder(ty::ProjectionPredicate {
|
ty::Binder(ty::ProjectionPredicate {
|
||||||
projection_ty: ty::ProjectionTy { trait_ref: trait_ref,
|
projection_ty: projection_ty,
|
||||||
item_name: item_name },
|
|
||||||
ty: ty_var
|
ty: ty_var
|
||||||
});
|
});
|
||||||
let obligation = Obligation::new(cause, projection.as_predicate());
|
let obligation = Obligation::new(cause, projection.as_predicate());
|
||||||
|
|
|
@ -117,7 +117,10 @@ pub enum ObligationCauseCode<'tcx> {
|
||||||
|
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct DerivedObligationCause<'tcx> {
|
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>,
|
parent_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
|
|
||||||
/// The parent trait had this cause
|
/// The parent trait had this cause
|
||||||
|
|
|
@ -20,7 +20,6 @@ use super::VtableImplData;
|
||||||
use middle::infer;
|
use middle::infer;
|
||||||
use middle::subst::Subst;
|
use middle::subst::Subst;
|
||||||
use middle::ty::{mod, AsPredicate, ToPolyTraitRef, Ty};
|
use middle::ty::{mod, AsPredicate, ToPolyTraitRef, Ty};
|
||||||
use std::fmt;
|
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
pub type PolyProjectionObligation<'tcx> =
|
pub type PolyProjectionObligation<'tcx> =
|
||||||
|
@ -34,10 +33,17 @@ pub type ProjectionTyObligation<'tcx> =
|
||||||
|
|
||||||
/// When attempting to resolve `<T as TraitRef>::Name == U`...
|
/// When attempting to resolve `<T as TraitRef>::Name == U`...
|
||||||
pub enum ProjectionError<'tcx> {
|
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,
|
NoCandidate,
|
||||||
|
|
||||||
|
/// ...we found multiple sources of information and couldn't resolve the ambiguity.
|
||||||
TooManyCandidates,
|
TooManyCandidates,
|
||||||
|
|
||||||
///
|
/// ...`<T as TraitRef::Name>` ws resolved to some type `V` that failed to unify with `U`
|
||||||
MismatchedTypes(MismatchedProjectionTypes<'tcx>),
|
MismatchedTypes(MismatchedProjectionTypes<'tcx>),
|
||||||
|
|
||||||
/// ...an error occurred matching `T : TraitRef`
|
/// ...an error occurred matching `T : TraitRef`
|
||||||
|
@ -380,12 +386,6 @@ fn confirm_candidate<'cx,'tcx>(
|
||||||
Ok(projected_ty)
|
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> {
|
impl<'tcx> Repr<'tcx> for ProjectionError<'tcx> {
|
||||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||||
match *self {
|
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> {
|
impl<'tcx> Repr<'tcx> for ProjectionTyCandidate<'tcx> {
|
||||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
|
|
|
@ -150,8 +150,15 @@ enum SelectionCandidate<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SelectionCandidateSet<'tcx> {
|
struct SelectionCandidateSet<'tcx> {
|
||||||
|
// a list of candidates that definitely apply to the current
|
||||||
|
// obligation (meaning: types unify).
|
||||||
vec: Vec<SelectionCandidate<'tcx>>,
|
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> {
|
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 {
|
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
|
/// where T : 'a
|
||||||
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
|
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
|
||||||
|
|
||||||
///
|
/// where <T as TraitRef>::Name == X, approximately.
|
||||||
|
/// See `ProjectionPredicate` struct for details.
|
||||||
Projection(PolyProjectionPredicate<'tcx>),
|
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)]
|
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||||
pub struct ProjectionTy<'tcx> {
|
pub struct ProjectionTy<'tcx> {
|
||||||
|
/// The trait reference `T as Trait<..>`.
|
||||||
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
pub trait_ref: Rc<ty::TraitRef<'tcx>>,
|
||||||
|
|
||||||
|
/// The name `N` of the associated type.
|
||||||
pub item_name: ast::Name,
|
pub item_name: ast::Name,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2179,6 +2185,12 @@ impl<'tcx> ParameterEnvironment<'tcx> {
|
||||||
/// - `generics`: the set of type parameters and their bounds
|
/// - `generics`: the set of type parameters and their bounds
|
||||||
/// - `ty`: the base types, which may reference the parameters defined
|
/// - `ty`: the base types, which may reference the parameters defined
|
||||||
/// in `generics`
|
/// 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)]
|
#[deriving(Clone, Show)]
|
||||||
pub struct TypeScheme<'tcx> {
|
pub struct TypeScheme<'tcx> {
|
||||||
pub generics: Generics<'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
|
/// 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()`
|
/// 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
|
/// 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>(
|
fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
decl_def_id: ast::DefId,
|
|
||||||
decl_generics: &ty::Generics<'tcx>,
|
decl_generics: &ty::Generics<'tcx>,
|
||||||
path: &ast::Path)
|
path: &ast::Path)
|
||||||
-> Substs<'tcx>
|
-> Substs<'tcx>
|
||||||
|
@ -280,7 +279,6 @@ fn ast_path_substs_for_ty<'tcx,AC,RS>(
|
||||||
create_substs_for_ast_path(this,
|
create_substs_for_ast_path(this,
|
||||||
rscope,
|
rscope,
|
||||||
path.span,
|
path.span,
|
||||||
decl_def_id,
|
|
||||||
decl_generics,
|
decl_generics,
|
||||||
None,
|
None,
|
||||||
types,
|
types,
|
||||||
|
@ -291,7 +289,6 @@ fn create_substs_for_ast_path<'tcx,AC,RS>(
|
||||||
this: &AC,
|
this: &AC,
|
||||||
rscope: &RS,
|
rscope: &RS,
|
||||||
span: Span,
|
span: Span,
|
||||||
_decl_def_id: ast::DefId,
|
|
||||||
decl_generics: &ty::Generics<'tcx>,
|
decl_generics: &ty::Generics<'tcx>,
|
||||||
self_ty: Option<Ty<'tcx>>,
|
self_ty: Option<Ty<'tcx>>,
|
||||||
types: Vec<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,
|
let substs = create_substs_for_ast_path(this,
|
||||||
&shifted_rscope,
|
&shifted_rscope,
|
||||||
path.span,
|
path.span,
|
||||||
trait_def_id,
|
|
||||||
&trait_def.generics,
|
&trait_def.generics,
|
||||||
self_ty,
|
self_ty,
|
||||||
types,
|
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,
|
let substs = ast_path_substs_for_ty(this,
|
||||||
rscope,
|
rscope,
|
||||||
did,
|
|
||||||
&generics,
|
&generics,
|
||||||
path);
|
path);
|
||||||
let ty = decl_ty.subst(tcx, &substs);
|
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),
|
Substs::new(VecPerParamSpace::params_from_type(type_params),
|
||||||
VecPerParamSpace::params_from_type(region_params))
|
VecPerParamSpace::params_from_type(region_params))
|
||||||
} else {
|
} 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);
|
let ty = decl_ty.subst(tcx, &substs);
|
||||||
|
|
|
@ -80,11 +80,9 @@ impl<'a,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'tcx> {
|
||||||
self.span,
|
self.span,
|
||||||
self.body_id,
|
self.body_id,
|
||||||
ObligationCauseCode::MiscObligation);
|
ObligationCauseCode::MiscObligation);
|
||||||
let trait_ref = data.trait_ref.clone();
|
|
||||||
self.fulfillment_cx
|
self.fulfillment_cx
|
||||||
.normalize_associated_type(self.infcx,
|
.normalize_projection_type(self.infcx,
|
||||||
trait_ref,
|
data.clone(),
|
||||||
data.item_name,
|
|
||||||
cause)
|
cause)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
|
|
@ -1758,9 +1758,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
traits::ObligationCauseCode::MiscObligation);
|
traits::ObligationCauseCode::MiscObligation);
|
||||||
self.inh.fulfillment_cx
|
self.inh.fulfillment_cx
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.normalize_associated_type(self.infcx(),
|
.normalize_projection_type(self.infcx(),
|
||||||
trait_ref,
|
ty::ProjectionTy {
|
||||||
item_name,
|
trait_ref: trait_ref,
|
||||||
|
item_name: item_name,
|
||||||
|
},
|
||||||
cause)
|
cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
|
// Helper for test issue-18048, which tests associated types in a
|
||||||
|
// cross-crate scenario.
|
||||||
|
|
||||||
#![crate_type="lib"]
|
#![crate_type="lib"]
|
||||||
#![feature(associated_types)]
|
#![feature(associated_types)]
|
||||||
|
|
|
@ -8,14 +8,14 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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
|
// Test that we are able to reference cross-crate traits that employ
|
||||||
// associated types.
|
// associated types.
|
||||||
|
|
||||||
#![feature(associated_types)]
|
#![feature(associated_types)]
|
||||||
|
|
||||||
extern crate "issue-18048-lib" as bar;
|
extern crate "associated-types-cc-lib" as bar;
|
||||||
|
|
||||||
use bar::Bar;
|
use bar::Bar;
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
// option. This file may not be copied, modified, or distributed
|
// option. This file may not be copied, modified, or distributed
|
||||||
// except according to those terms.
|
// 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)]
|
#![feature(associated_types)]
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue