1
Fork 0

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

View file

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

View file

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

View file

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

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

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

View file

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

View file

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

View file

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

View file

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

View file

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