Address nits.

This commit is contained in:
Niko Matsakis 2014-12-30 08:59:33 -05:00
parent 518ec1259a
commit 919975d0a5
12 changed files with 75 additions and 45 deletions

View File

@ -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());

View File

@ -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

View File

@ -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 {

View File

@ -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> {

View File

@ -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(..)")
}
}

View File

@ -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

View File

@ -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);

View File

@ -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)
}
_ => {

View File

@ -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)
}

View File

@ -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)]

View File

@ -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;

View File

@ -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)]