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;
}
}
- 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());
#[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
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> =
/// 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`
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 {
}
}
-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 {
}
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> {
}
}
-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(..)")
+ }
+}
+
+
/// where T : 'a
TypeOutlives(PolyTypeOutlivesPredicate<'tcx>),
- ///
+ /// where <T as TraitRef>::Name == X, approximately.
+ /// See `ProjectionPredicate` struct for details.
Projection(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,
}
/// - `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>,
}
}
+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
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>
create_substs_for_ast_path(this,
rscope,
path.span,
- decl_def_id,
decl_generics,
None,
types,
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>>,
let substs = create_substs_for_ast_path(this,
&shifted_rscope,
path.span,
- trait_def_id,
&trait_def.generics,
self_ty,
types,
let substs = ast_path_substs_for_ty(this,
rscope,
- did,
&generics,
path);
let ty = decl_ty.subst(tcx, &substs);
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);
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)
}
_ => {
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)
}
--- /dev/null
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// 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)]
+
+pub trait Bar {
+ type T;
+
+ fn get(x: Option<Self>) -> <Self as Bar>::T;
+}
+
+impl Bar for int {
+ type T = uint;
+
+ fn get(_: Option<int>) -> uint { 22 }
+}
+++ /dev/null
-// Copyright 2014 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![crate_type="lib"]
-#![feature(associated_types)]
-
-pub trait Bar {
- type T;
-
- fn get(x: Option<Self>) -> <Self as Bar>::T;
-}
-
-impl Bar for int {
- type T = uint;
-
- fn get(_: Option<int>) -> uint { 22 }
-}
--- /dev/null
+// Copyright 2014 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// 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 "associated-types-cc-lib" as bar;
+
+use bar::Bar;
+
+fn foo<B:Bar>(b: B) -> <B as Bar>::T {
+ Bar::get(None::<B>)
+}
+
+fn main() {
+ println!("{}", foo(3i));
+}
+++ /dev/null
-// Copyright 2014 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 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// aux-build:issue-18048-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;
-
-use bar::Bar;
-
-fn foo<B:Bar>(b: B) -> <B as Bar>::T {
- Bar::get(None::<B>)
-}
-
-fn main() {
- println!("{}", foo(3i));
-}
// 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)]