diff options
| author | Eduard Burtescu <edy.burt@gmail.com> | 2016-07-22 18:56:22 +0300 |
|---|---|---|
| committer | Eduard Burtescu <edy.burt@gmail.com> | 2016-08-12 06:43:34 +0300 |
| commit | ef11d4e3c7040bf7cbb351dac8317a7957471b3b (patch) | |
| tree | 163620cf8be4fda40f6e91281db5d64e501f7edf /src | |
| parent | f0baec691f9bfcfc70d6f35b1a86f7cf204a7d4f (diff) | |
| download | rust-ef11d4e3c7040bf7cbb351dac8317a7957471b3b.tar.gz rust-ef11d4e3c7040bf7cbb351dac8317a7957471b3b.zip | |
rustc: add TyAnon (impl Trait) to the typesystem.
Diffstat (limited to 'src')
40 files changed, 250 insertions, 85 deletions
diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 58bbd8add26..752b0e9a253 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -268,6 +268,9 @@ impl<'ast> visit::Visitor for DefCollector<'ast> { if let TyKind::FixedLengthVec(_, ref length) = ty.node { self.visit_ast_const_integer(length); } + if let TyKind::ImplTrait(..) = ty.node { + self.create_def(ty.id, DefPathData::ImplTrait); + } visit::walk_ty(self, ty); } @@ -428,6 +431,9 @@ impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> { if let hir::TyFixedLengthVec(_, ref length) = ty.node { self.visit_hir_const_integer(length); } + if let hir::TyImplTrait(..) = ty.node { + self.create_def(ty.id, DefPathData::ImplTrait); + } intravisit::walk_ty(self, ty); } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index e3425d7fa61..901a489728e 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -215,6 +215,8 @@ pub enum DefPathData { Initializer, /// Pattern binding Binding(InternedString), + /// An `impl Trait` type node. + ImplTrait } impl Definitions { @@ -369,6 +371,10 @@ impl DefPathData { Initializer => { InternedString::new("{{initializer}}") } + + ImplTrait => { + InternedString::new("{{impl-Trait}}") + } } } diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs index 880661a882a..1fb4e59e131 100644 --- a/src/librustc/infer/freshen.rs +++ b/src/librustc/infer/freshen.rs @@ -170,7 +170,8 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for TypeFreshener<'a, 'gcx, 'tcx> { ty::TyClosure(..) | ty::TyTuple(..) | ty::TyProjection(..) | - ty::TyParam(..) => { + ty::TyParam(..) | + ty::TyAnon(..) => { t.super_fold_with(self) } } diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs index 4344eb1ebf6..37193d45e68 100644 --- a/src/librustc/traits/coherence.rs +++ b/src/librustc/traits/coherence.rs @@ -281,7 +281,7 @@ fn ty_is_local_constructor(tcx: TyCtxt, ty: Ty, infer_is_local: InferIsLocal)-> true } - ty::TyClosure(..) => { + ty::TyClosure(..) | ty::TyAnon(..) => { bug!("ty_is_local invoked on unexpected type: {:?}", ty) } } diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 62a31133a54..09b5a34fdf3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -211,6 +211,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::TyTuple(..) => Some(12), ty::TyProjection(..) => Some(13), ty::TyParam(..) => Some(14), + ty::TyAnon(..) => Some(15), ty::TyInfer(..) | ty::TyError => None } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index b93693cd756..aed4f439324 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -94,6 +94,16 @@ pub enum Reveal { NotSpecializable, /// At trans time, all monomorphic projections will succeed. + /// Also, `impl Trait` is normalized to the concrete type, + /// which has to be already collected by type-checking. + /// + /// NOTE: As `impl Trait`'s concrete type should *never* + /// be observable directly by the user, `Reveal::All` + /// should not be used by checks which may expose + /// type equality or type contents to the user. + /// There are some exceptions, e.g. around OIBITS and + /// transmute-checking, which expose some details, but + /// not the whole concrete type of the `impl Trait`. All, } @@ -298,6 +308,17 @@ impl<'a, 'b, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for AssociatedTypeNormalizer<'a, let ty = ty.super_fold_with(self); match ty.sty { + ty::TyAnon(def_id, substs) if !substs.has_escaping_regions() => { // (*) + // Only normalize `impl Trait` after type-checking, usually in trans. + if self.selcx.projection_mode() == Reveal::All { + let generic_ty = self.tcx().lookup_item_type(def_id).ty; + let concrete_ty = generic_ty.subst(self.tcx(), substs); + self.fold_ty(concrete_ty) + } else { + ty + } + } + ty::TyProjection(ref data) if !data.has_escaping_regions() => { // (*) // (*) This is kind of hacky -- we need to be able to @@ -773,8 +794,11 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( debug!("assemble_candidates_from_trait_def(..)"); // Check whether the self-type is itself a projection. - let trait_ref = match obligation_trait_ref.self_ty().sty { - ty::TyProjection(ref data) => data.trait_ref.clone(), + let (def_id, substs) = match obligation_trait_ref.self_ty().sty { + ty::TyProjection(ref data) => { + (data.trait_ref.def_id, data.trait_ref.substs) + } + ty::TyAnon(def_id, substs) => (def_id, substs), ty::TyInfer(ty::TyVar(_)) => { // If the self-type is an inference variable, then it MAY wind up // being a projected type, so induce an ambiguity. @@ -785,8 +809,8 @@ fn assemble_candidates_from_trait_def<'cx, 'gcx, 'tcx>( }; // If so, extract what we know from the trait and try to come up with a good answer. - let trait_predicates = selcx.tcx().lookup_predicates(trait_ref.def_id); - let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs); + let trait_predicates = selcx.tcx().lookup_predicates(def_id); + let bounds = trait_predicates.instantiate(selcx.tcx(), substs); let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec()); assemble_candidates_from_predicates(selcx, obligation, diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs index 028d05731b6..f353c54089d 100644 --- a/src/librustc/traits/select.rs +++ b/src/librustc/traits/select.rs @@ -1158,20 +1158,17 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { // before we go into the whole skolemization thing, just // quickly check if the self-type is a projection at all. - let trait_def_id = match obligation.predicate.0.trait_ref.self_ty().sty { - ty::TyProjection(ref data) => data.trait_ref.def_id, + match obligation.predicate.0.trait_ref.self_ty().sty { + ty::TyProjection(_) | ty::TyAnon(..) => {} ty::TyInfer(ty::TyVar(_)) => { span_bug!(obligation.cause.span, "Self=_ should have been handled by assemble_candidates"); } - _ => { return; } - }; - - debug!("assemble_candidates_for_projected_tys: trait_def_id={:?}", - trait_def_id); + _ => return + } let result = self.probe(|this, snapshot| { - this.match_projection_obligation_against_bounds_from_trait(obligation, + this.match_projection_obligation_against_definition_bounds(obligation, snapshot) }); @@ -1180,7 +1177,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } - fn match_projection_obligation_against_bounds_from_trait( + fn match_projection_obligation_against_definition_bounds( &mut self, obligation: &TraitObligation<'tcx>, snapshot: &infer::CombinedSnapshot) @@ -1190,28 +1187,29 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { self.infcx().resolve_type_vars_if_possible(&obligation.predicate); let (skol_trait_predicate, skol_map) = self.infcx().skolemize_late_bound_regions(&poly_trait_predicate, snapshot); - debug!("match_projection_obligation_against_bounds_from_trait: \ + debug!("match_projection_obligation_against_definition_bounds: \ skol_trait_predicate={:?} skol_map={:?}", skol_trait_predicate, skol_map); - let projection_trait_ref = match skol_trait_predicate.trait_ref.self_ty().sty { - ty::TyProjection(ref data) => &data.trait_ref, + let (def_id, substs) = match skol_trait_predicate.trait_ref.self_ty().sty { + ty::TyProjection(ref data) => (data.trait_ref.def_id, data.trait_ref.substs), + ty::TyAnon(def_id, substs) => (def_id, substs), _ => { span_bug!( obligation.cause.span, - "match_projection_obligation_against_bounds_from_trait() called \ + "match_projection_obligation_against_definition_bounds() called \ but self-ty not a projection: {:?}", skol_trait_predicate.trait_ref.self_ty()); } }; - debug!("match_projection_obligation_against_bounds_from_trait: \ - projection_trait_ref={:?}", - projection_trait_ref); + debug!("match_projection_obligation_against_definition_bounds: \ + def_id={:?}, substs={:?}", + def_id, substs); - let trait_predicates = self.tcx().lookup_predicates(projection_trait_ref.def_id); - let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs); - debug!("match_projection_obligation_against_bounds_from_trait: \ + let item_predicates = self.tcx().lookup_predicates(def_id); + let bounds = item_predicates.instantiate(self.tcx(), substs); + debug!("match_projection_obligation_against_definition_bounds: \ bounds={:?}", bounds); @@ -1226,7 +1224,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { &skol_map, snapshot))); - debug!("match_projection_obligation_against_bounds_from_trait: \ + debug!("match_projection_obligation_against_definition_bounds: \ matching_bound={:?}", matching_bound); match matching_bound { @@ -1472,7 +1470,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { } } ty::TyParam(..) | - ty::TyProjection(..) => { + ty::TyProjection(..) | + ty::TyAnon(..) => { // In these cases, we don't know what the actual // type is. Therefore, we cannot break it down // into its constituent types. So we don't @@ -1796,7 +1795,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { })) } - ty::TyProjection(_) | ty::TyParam(_) => None, + ty::TyProjection(_) | ty::TyParam(_) | ty::TyAnon(..) => None, ty::TyInfer(ty::TyVar(_)) => Ambiguous, ty::TyInfer(ty::FreshTy(_)) @@ -1842,7 +1841,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { Where(ty::Binder(tys.to_vec())) } - ty::TyStruct(..) | ty::TyEnum(..) | ty::TyProjection(..) | ty::TyParam(..) => { + ty::TyStruct(..) | ty::TyEnum(..) | + ty::TyProjection(..) | ty::TyParam(..) | ty::TyAnon(..) => { // Fallback to whatever user-defined impls exist in this case. None } @@ -1893,6 +1893,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { ty::TyTrait(..) | ty::TyParam(..) | ty::TyProjection(..) | + ty::TyAnon(..) | ty::TyInfer(ty::TyVar(_)) | ty::TyInfer(ty::FreshTy(_)) | ty::TyInfer(ty::FreshIntTy(_)) | @@ -2073,7 +2074,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> { { self.in_snapshot(|this, snapshot| { let result = - this.match_projection_obligation_against_bounds_from_trait(obligation, + this.match_projection_obligation_against_definition_bounds(obligation, snapshot); assert!(result); }) diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs index 14b0a807098..8da7568c558 100644 --- a/src/librustc/ty/contents.rs +++ b/src/librustc/ty/contents.rs @@ -240,7 +240,8 @@ impl<'a, 'tcx> ty::TyS<'tcx> { } ty::TyProjection(..) | - ty::TyParam(_) => { + ty::TyParam(_) | + ty::TyAnon(..) => { TC::All } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a816d26edad..13401e91265 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1016,7 +1016,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { sty_debug_print!( self, TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyFnDef, TyFnPtr, - TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection); + TyTrait, TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection, TyAnon); println!("Substs interner: #{}", self.interners.substs.borrow().len()); println!("BareFnTy interner: #{}", self.interners.bare_fn.borrow().len()); @@ -1355,6 +1355,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.mk_param(def.space, def.index, def.name) } + pub fn mk_anon(self, def_id: DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { + self.mk_ty(TyAnon(def_id, substs)) + } + pub fn trait_items(self, trait_did: DefId) -> Rc<Vec<ty::ImplOrTraitItem<'gcx>>> { self.trait_items_cache.memoize(trait_did, || { let def_ids = self.trait_item_def_ids(trait_did); diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index bddc2dbdb7e..66165ec6ff7 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -247,6 +247,7 @@ impl<'a, 'gcx, 'lcx, 'tcx> ty::TyS<'tcx> { "type parameter".to_string() } } + ty::TyAnon(..) => "anonymized type".to_string(), ty::TyError => "type error".to_string(), } } diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs index 25f3552b565..e6f2ba8b650 100644 --- a/src/librustc/ty/fast_reject.rs +++ b/src/librustc/ty/fast_reject.rs @@ -30,6 +30,7 @@ pub enum SimplifiedType { TraitSimplifiedType(DefId), StructSimplifiedType(DefId), ClosureSimplifiedType(DefId), + AnonSimplifiedType(DefId), FunctionSimplifiedType(usize), ParameterSimplifiedType, } @@ -98,6 +99,9 @@ pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, None } } + ty::TyAnon(def_id, _) => { + Some(AnonSimplifiedType(def_id)) + } ty::TyInfer(_) | ty::TyError => None, } } diff --git a/src/librustc/ty/flags.rs b/src/librustc/ty/flags.rs index 44b450784ed..85b7d66a2eb 100644 --- a/src/librustc/ty/flags.rs +++ b/src/librustc/ty/flags.rs @@ -110,6 +110,11 @@ impl FlagComputation { self.add_projection_ty(data); } + &ty::TyAnon(_, substs) => { + self.add_flags(TypeFlags::HAS_PROJECTION); + self.add_substs(substs); + } + &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { let mut computation = FlagComputation::new(); computation.add_substs(principal.0.substs); diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index b334964bf48..3580013c2a9 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -695,7 +695,7 @@ impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector { // in the normalized form if self.just_constrained { match t.sty { - ty::TyProjection(..) => { return false; } + ty::TyProjection(..) | ty::TyAnon(..) => { return false; } _ => { } } } diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs index 74c05feb6d1..bfe6303d8a3 100644 --- a/src/librustc/ty/item_path.rs +++ b/src/librustc/ty/item_path.rs @@ -188,7 +188,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { data @ DefPathData::Initializer | data @ DefPathData::MacroDef(..) | data @ DefPathData::ClosureExpr | - data @ DefPathData::Binding(..) => { + data @ DefPathData::Binding(..) | + data @ DefPathData::ImplTrait => { let parent_def_id = self.parent_def_id(def_id).unwrap(); self.push_item_path(buffer, parent_def_id); buffer.push(&data.as_interned_str()); @@ -345,6 +346,7 @@ pub fn characteristic_def_id_of_type(ty: Ty) -> Option<DefId> { ty::TyFnPtr(_) | ty::TyProjection(_) | ty::TyParam(_) | + ty::TyAnon(..) | ty::TyInfer(_) | ty::TyError | ty::TyFloat(_) => None, diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e27a9d79b62..d73e412f55f 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -594,7 +594,7 @@ impl<'a, 'gcx, 'tcx> Struct { Struct::non_zero_field_path(infcx, Some(ety).into_iter()) } - (_, &ty::TyProjection(_)) => { + (_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => { let normalized = normalize_associated_type(infcx, ty); if ty == normalized { return Ok(None); @@ -1108,7 +1108,7 @@ impl<'a, 'gcx, 'tcx> Layout { } // Types with no meaningful known layout. - ty::TyProjection(_) => { + ty::TyProjection(_) | ty::TyAnon(..) => { let normalized = normalize_associated_type(infcx, ty); if ty == normalized { return Err(LayoutError::Unknown(ty)); @@ -1332,7 +1332,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> { } } - ty::TyProjection(_) => { + ty::TyProjection(_) | ty::TyAnon(..) => { let normalized = normalize_associated_type(infcx, ty); if ty == normalized { Err(err) diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index a7c53419892..fe5c602575b 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1885,7 +1885,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> { } } - TyProjection(..) => { + TyProjection(..) | TyAnon(..) => { // must calculate explicitly. // FIXME: consider special-casing always-Sized projections vec![ty] diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs index 9ae3325c258..df907c26f71 100644 --- a/src/librustc/ty/outlives.rs +++ b/src/librustc/ty/outlives.rs @@ -174,6 +174,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ty::TyEnum(..) | // OutlivesNominalType ty::TyStruct(..) | // OutlivesNominalType ty::TyBox(..) | // OutlivesNominalType (ish) + ty::TyAnon(..) | // OutlivesNominalType (ish) ty::TyStr | // OutlivesScalar (ish) ty::TyArray(..) | // ... ty::TySlice(..) | // ... diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index 80c727f0221..f9263947c03 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -582,6 +582,13 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, R>(relation: &mut R, Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name)) } + (&ty::TyAnon(a_def_id, a_substs), &ty::TyAnon(b_def_id, b_substs)) + if a_def_id == b_def_id => + { + let substs = relate_substs(relation, None, a_substs, b_substs)?; + Ok(tcx.mk_anon(a_def_id, substs)) + } + _ => { Err(TypeError::Sorts(expected_found(relation, &a, &b))) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 16a54c20925..e542e8f237f 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -485,6 +485,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyStruct(did, substs) => ty::TyStruct(did, substs.fold_with(folder)), ty::TyClosure(did, substs) => ty::TyClosure(did, substs.fold_with(folder)), ty::TyProjection(ref data) => ty::TyProjection(data.fold_with(folder)), + ty::TyAnon(did, substs) => ty::TyAnon(did, substs.fold_with(folder)), ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | ty::TyParam(..) => self.sty.clone(), @@ -513,6 +514,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::TyStruct(_did, ref substs) => substs.visit_with(visitor), ty::TyClosure(_did, ref substs) => substs.visit_with(visitor), ty::TyProjection(ref data) => data.visit_with(visitor), + ty::TyAnon(_, ref substs) => substs.visit_with(visitor), ty::TyBool | ty::TyChar | ty::TyStr | ty::TyInt(_) | ty::TyUint(_) | ty::TyFloat(_) | ty::TyError | ty::TyInfer(_) | ty::TyParam(..) => false, diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 7c69618068a..912cb39face 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -166,6 +166,12 @@ pub enum TypeVariants<'tcx> { /// `<T as Trait<..>>::N`. TyProjection(ProjectionTy<'tcx>), + /// Anonymized (`impl Trait`) type found in a return type. + /// The DefId comes from the `impl Trait` ast::Ty node, and the + /// substitutions are for the generics of the function in question. + /// After typeck, the concrete type can be found in the `tcache` map. + TyAnon(DefId, &'tcx Substs<'tcx>), + /// A type parameter; for example, `T` in `fn f<T>(x: T) {} TyParam(ParamTy), @@ -1232,7 +1238,8 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { v } TyEnum(_, substs) | - TyStruct(_, substs) => { + TyStruct(_, substs) | + TyAnon(_, substs) => { substs.regions.as_slice().to_vec() } TyClosure(_, ref substs) => { diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs index 07439d7104a..e7bcfbfd823 100644 --- a/src/librustc/ty/util.rs +++ b/src/librustc/ty/util.rs @@ -437,6 +437,7 @@ impl<'a, 'gcx, 'tcx> TypeVisitor<'tcx> for TypeIdHasher<'a, 'gcx, 'tcx> { TyRawPtr(m) | TyRef(_, m) => self.hash(m.mutbl), TyClosure(def_id, _) | + TyAnon(def_id, _) | TyFnDef(def_id, _, _) => self.def_id(def_id), TyFnPtr(f) => { self.hash(f.unsafety); @@ -559,7 +560,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { }) => Some(true), TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) | - TyClosure(..) | TyEnum(..) | TyStruct(..) | + TyClosure(..) | TyEnum(..) | TyStruct(..) | TyAnon(..) | TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None }.unwrap_or_else(|| !self.impls_bound(tcx, param_env, ty::BoundCopy, span)); @@ -600,7 +601,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> { TyStr | TyTrait(..) | TySlice(_) => Some(false), TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) | - TyInfer(..) | TyError => None + TyInfer(..) | TyAnon(..) | TyError => None }.unwrap_or_else(|| self.impls_bound(tcx, param_env, ty::BoundSized, span)); if !self.has_param_types() && !self.has_self_ty() { diff --git a/src/librustc/ty/walk.rs b/src/librustc/ty/walk.rs index fa7c9b78231..ebc2642678b 100644 --- a/src/librustc/ty/walk.rs +++ b/src/librustc/ty/walk.rs @@ -88,7 +88,8 @@ fn push_subtypes<'tcx>(stack: &mut Vec<Ty<'tcx>>, parent_ty: Ty<'tcx>) { }).collect::<Vec<_>>()); } ty::TyEnum(_, ref substs) | - ty::TyStruct(_, ref substs) => { + ty::TyStruct(_, ref substs) | + ty::TyAnon(_, ref substs) => { push_reversed(stack, substs.types.as_slice()); } ty::TyClosure(_, ref substs) => { diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs index 37ba936d2f4..f6ddfe60d40 100644 --- a/src/librustc/ty/wf.rs +++ b/src/librustc/ty/wf.rs @@ -383,6 +383,12 @@ impl<'a, 'gcx, 'tcx> WfPredicates<'a, 'gcx, 'tcx> { // types appearing in the fn signature } + ty::TyAnon(..) => { + // all of the requirements on type parameters + // should've been checked by the instantiation + // of whatever returned this exact `impl Trait`. + } + ty::TyTrait(ref data) => { // WfObject // diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 60977a80946..a17c0106813 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -907,6 +907,37 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> { } TyTrait(ref data) => write!(f, "{}", data), ty::TyProjection(ref data) => write!(f, "{}", data), + ty::TyAnon(def_id, substs) => { + ty::tls::with(|tcx| { + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let item_predicates = tcx.lookup_predicates(def_id); + let substs = tcx.lift(&substs).unwrap_or_else(|| { + tcx.mk_substs(subst::Substs::empty()) + }); + let bounds = item_predicates.instantiate(tcx, substs); + + let mut first = true; + let mut is_sized = false; + write!(f, "impl")?; + for predicate in bounds.predicates.into_vec() { + if let Some(trait_ref) = predicate.to_opt_poly_trait_ref() { + // Don't print +Sized, but rather +?Sized if absent. + if Some(trait_ref.def_id()) == tcx.lang_items.sized_trait() { + is_sized = true; + continue; + } + + write!(f, "{}{}", if first { " " } else { "+" }, trait_ref)?; + first = false; + } + } + if !is_sized { + write!(f, "{}?Sized", if first { " " } else { "+" })?; + } + Ok(()) + }) + } TyStr => write!(f, "str"), TyClosure(did, substs) => ty::tls::with(|tcx| { write!(f, "[closure")?; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 09dd8748b30..b9861c309db 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -596,7 +596,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } ty::TyParam(..) | ty::TyInfer(..) | ty::TyError | - ty::TyClosure(..) | ty::TyProjection(..) | + ty::TyClosure(..) | ty::TyProjection(..) | ty::TyAnon(..) | ty::TyFnDef(..) => { bug!("Unexpected type in foreign function") } diff --git a/src/librustc_metadata/def_key.rs b/src/librustc_metadata/def_key.rs index 2444d669f7f..285ca2e4d4d 100644 --- a/src/librustc_metadata/def_key.rs +++ b/src/librustc_metadata/def_key.rs @@ -41,6 +41,7 @@ pub enum DefPathData { StructCtor, Initializer, Binding, + ImplTrait, } pub fn simplify_def_key(key: hir_map::DefKey) -> DefKey { @@ -72,6 +73,7 @@ fn simplify_def_path_data(data: hir_map::DefPathData) -> DefPathData { hir_map::DefPathData::StructCtor => DefPathData::StructCtor, hir_map::DefPathData::Initializer => DefPathData::Initializer, hir_map::DefPathData::Binding(_) => DefPathData::Binding, + hir_map::DefPathData::ImplTrait => DefPathData::ImplTrait, } } @@ -103,5 +105,6 @@ fn recover_def_path_data(data: DefPathData, name: Option<InternedString>) -> hir DefPathData::StructCtor => hir_map::DefPathData::StructCtor, DefPathData::Initializer => hir_map::DefPathData::Initializer, DefPathData::Binding => hir_map::DefPathData::Binding(name.unwrap()), + DefPathData::ImplTrait => hir_map::DefPathData::ImplTrait, } } diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs index 119640af463..1dcec35adb2 100644 --- a/src/librustc_metadata/tydecode.rs +++ b/src/librustc_metadata/tydecode.rs @@ -445,6 +445,13 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> { let name = token::intern(&self.parse_str(']')); return tcx.mk_projection(trait_ref, name); } + 'A' => { + assert_eq!(self.next(), '['); + let def_id = self.parse_def(); + let substs = self.parse_substs(); + assert_eq!(self.next(), ']'); + return self.tcx.mk_anon(def_id, self.tcx.mk_substs(substs)); + } 'e' => { return tcx.types.err; } diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs index 3484a8b75dd..c2e91eba0d2 100644 --- a/src/librustc_metadata/tyencode.rs +++ b/src/librustc_metadata/tyencode.rs @@ -170,6 +170,11 @@ pub fn enc_ty<'a, 'tcx>(w: &mut Cursor<Vec<u8>>, cx: &ctxt<'a, 'tcx>, t: Ty<'tcx enc_trait_ref(w, cx, data.trait_ref); write!(w, "{}]", data.item_name); } + ty::TyAnon(def_id, substs) => { + write!(w, "A[{}|", (cx.ds)(cx.tcx, def_id)); + enc_substs(w, cx, substs); + write!(w, "]"); + } ty::TyError => { write!(w, "e"); } diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs index 58b49f6944f..4a6dbb2bdae 100644 --- a/src/librustc_trans/collector.rs +++ b/src/librustc_trans/collector.rs @@ -796,6 +796,7 @@ fn find_drop_glue_neighbors<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>, ty::TyProjection(_) | ty::TyParam(_) | ty::TyInfer(_) | + ty::TyAnon(..) | ty::TyError => { bug!("encountered unexpected type"); } diff --git a/src/librustc_trans/debuginfo/type_names.rs b/src/librustc_trans/debuginfo/type_names.rs index 63f460e4693..bee2667c71f 100644 --- a/src/librustc_trans/debuginfo/type_names.rs +++ b/src/librustc_trans/debuginfo/type_names.rs @@ -150,6 +150,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::TyError | ty::TyInfer(_) | ty::TyProjection(..) | + ty::TyAnon(..) | ty::TyParam(_) => { bug!("debuginfo: Trying to create type name for \ unexpected type: {:?}", t); diff --git a/src/librustc_trans/trans_item.rs b/src/librustc_trans/trans_item.rs index d0e00a6d593..187ffe353fd 100644 --- a/src/librustc_trans/trans_item.rs +++ b/src/librustc_trans/trans_item.rs @@ -536,7 +536,8 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty::TyError | ty::TyInfer(_) | ty::TyProjection(..) | - ty::TyParam(_) => { + ty::TyParam(_) | + ty::TyAnon(..) => { bug!("debuginfo: Trying to create type name for \ unexpected type: {:?}", t); } diff --git a/src/librustc_trans/type_of.rs b/src/librustc_trans/type_of.rs index 496870d6c27..cde53f6fa89 100644 --- a/src/librustc_trans/type_of.rs +++ b/src/librustc_trans/type_of.rs @@ -112,7 +112,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ } } - ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => { + ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | + ty::TyAnon(..) | ty::TyError => { bug!("fictitious type {:?} in sizing_type_of()", t) } ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => bug!() @@ -339,10 +340,11 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> } } - ty::TyInfer(..) => bug!("type_of with TyInfer"), - ty::TyProjection(..) => bug!("type_of with TyProjection"), - ty::TyParam(..) => bug!("type_of with ty_param"), - ty::TyError => bug!("type_of with TyError"), + ty::TyInfer(..) | + ty::TyProjection(..) | + ty::TyParam(..) | + ty::TyAnon(..) | + ty::TyError => bug!("type_of with {:?}", t), }; debug!("--> mapped t={:?} to llty={:?}", t, llty); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 07595c5dbe1..f1d2bdb0117 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -56,6 +56,7 @@ use hir::print as pprust; use middle::resolve_lifetime as rl; use rustc::lint; use rustc::ty::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs, ParamSpace}; +use rustc::ty::subst::VecPerParamSpace; use rustc::traits; use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::wf::object_region_bounds; @@ -1745,6 +1746,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { hir::TyPolyTraitRef(ref bounds) => { self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds) } + hir::TyImplTrait(ref bounds) => { + use collect::{compute_bounds, SizedByDefault}; + + // Create the anonymized type. + let def_id = tcx.map.local_def_id(ast_ty.id); + let substs = tcx.mk_substs(Substs::empty()); + let ty = tcx.mk_anon(tcx.map.local_def_id(ast_ty.id), substs); + + // Collect the bounds, i.e. the `Trait` in `impl Trait`. + let bounds = compute_bounds(self, ty, bounds, SizedByDefault::Yes, ast_ty.span); + let predicates = tcx.lift_to_global(&bounds.predicates(tcx, ty)).unwrap(); + let predicates = ty::GenericPredicates { + predicates: VecPerParamSpace::new(vec![], vec![], predicates) + }; + tcx.predicates.borrow_mut().insert(def_id, predicates); + + ty + } hir::TyPath(ref maybe_qself, ref path) => { debug!("ast_ty_to_ty: maybe_qself={:?} path={:?}", maybe_qself, path); let path_res = tcx.expect_resolution(ast_ty.id); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 0791c76c712..f65e15430da 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -499,7 +499,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>( } // these are always dtorck - ty::TyTrait(..) | ty::TyProjection(_) => bug!(), + ty::TyTrait(..) | ty::TyProjection(_) | ty::TyAnon(..) => bug!(), } } @@ -509,7 +509,7 @@ fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, ty::TyEnum(def, _) | ty::TyStruct(def, _) => { def.is_dtorck(tcx) } - ty::TyTrait(..) | ty::TyProjection(..) => { + ty::TyTrait(..) | ty::TyProjection(..) | ty::TyAnon(..) => { debug!("ty: {:?} isn't known, and therefore is a dropck type", ty); true }, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 648d1f42fb5..99f1b13d4e4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -786,16 +786,19 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { debug!("assemble_projection_candidates: step={:?}", step); - let projection_trait_ref = match step.self_ty.sty { - ty::TyProjection(ref data) => &data.trait_ref, + let (def_id, substs) = match step.self_ty.sty { + ty::TyProjection(ref data) => { + (data.trait_ref.def_id, data.trait_ref.substs) + } + ty::TyAnon(def_id, substs) => (def_id, substs), _ => continue, }; - debug!("assemble_projection_candidates: projection_trait_ref={:?}", - projection_trait_ref); + debug!("assemble_projection_candidates: def_id={:?} substs={:?}", + def_id, substs); - let trait_predicates = self.tcx.lookup_predicates(projection_trait_ref.def_id); - let bounds = trait_predicates.instantiate(self.tcx, projection_trait_ref.substs); + let trait_predicates = self.tcx.lookup_predicates(def_id); + let bounds = trait_predicates.instantiate(self.tcx, substs); let predicates = bounds.predicates.into_vec(); debug!("assemble_projection_candidates: predicates={:?}", predicates); @@ -806,9 +809,8 @@ impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> { { let bound = self.erase_late_bound_regions(&poly_bound); - debug!("assemble_projection_candidates: projection_trait_ref={:?} bound={:?}", - projection_trait_ref, - bound); + debug!("assemble_projection_candidates: def_id={:?} substs={:?} bound={:?}", + def_id, substs, bound); if self.can_equate(&step.self_ty, &bound.self_ty()).is_ok() { let xform_self_ty = self.xform_self_ty(&item, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 3e6df0ca5bb..13deac57330 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -27,7 +27,7 @@ use rustc::ty::{TyParam, TyRawPtr}; use rustc::ty::{TyRef, TyStruct, TyTrait, TyTuple}; use rustc::ty::{TyStr, TyArray, TySlice, TyFloat, TyInfer, TyInt}; use rustc::ty::{TyUint, TyClosure, TyBox, TyFnDef, TyFnPtr}; -use rustc::ty::TyProjection; +use rustc::ty::{TyProjection, TyAnon}; use rustc::ty::util::CopyImplementationError; use middle::free_region::FreeRegionMap; use CrateCtxt; @@ -89,7 +89,7 @@ impl<'a, 'gcx, 'tcx> CoherenceChecker<'a, 'gcx, 'tcx> { None } - TyInfer(..) | TyClosure(..) => { + TyInfer(..) | TyClosure(..) | TyAnon(..) => { // `ty` comes from a user declaration so we should only expect types // that the user can type span_bug!( diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index f68d902ef36..480a166f56a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -1694,10 +1694,10 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } // Add the Sized bound, unless the type parameter is marked as `?Sized`. -fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, - bounds: &mut ty::BuiltinBounds, - ast_bounds: &[hir::TyParamBound], - span: Span) +fn add_unsized_bound<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + bounds: &mut ty::BuiltinBounds, + ast_bounds: &[hir::TyParamBound], + span: Span) { let tcx = astconv.tcx(); @@ -2038,17 +2038,17 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, } } -enum SizedByDefault { Yes, No, } +pub enum SizedByDefault { Yes, No, } /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the /// built-in trait (formerly known as kind): Send. -fn compute_bounds<'tcx>(astconv: &AstConv<'tcx, 'tcx>, - param_ty: ty::Ty<'tcx>, - ast_bounds: &[hir::TyParamBound], - sized_by_default: SizedByDefault, - span: Span) - -> Bounds<'tcx> +pub fn compute_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + param_ty: ty::Ty<'tcx>, + ast_bounds: &[hir::TyParamBound], + sized_by_default: SizedByDefault, + span: Span) + -> Bounds<'tcx> { let mut bounds = conv_param_bounds(astconv, @@ -2098,11 +2098,11 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>, } } -fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>, - param_ty: Ty<'tcx>, - trait_ref: &hir::PolyTraitRef, - projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>) - -> ty::PolyTraitRef<'tcx> +fn conv_poly_trait_ref<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + param_ty: Ty<'tcx>, + trait_ref: &hir::PolyTraitRef, + projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>) + -> ty::PolyTraitRef<'tcx> { AstConv::instantiate_poly_trait_ref(astconv, &ExplicitRscope, @@ -2111,11 +2111,11 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>, projections) } -fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx, 'tcx>, - span: Span, - param_ty: ty::Ty<'tcx>, - ast_bounds: &[hir::TyParamBound]) - -> Bounds<'tcx> +fn conv_param_bounds<'gcx: 'tcx, 'tcx>(astconv: &AstConv<'gcx, 'tcx>, + span: Span, + param_ty: ty::Ty<'tcx>, + ast_bounds: &[hir::TyParamBound]) + -> Bounds<'tcx> { let tcx = astconv.tcx(); let PartitionedBounds { diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs index 7909584bfab..7d3bd095a3a 100644 --- a/src/librustc_typeck/constrained_type_params.rs +++ b/src/librustc_typeck/constrained_type_params.rs @@ -45,7 +45,7 @@ struct ParameterCollector { impl<'tcx> TypeVisitor<'tcx> for ParameterCollector { fn visit_ty(&mut self, t: Ty<'tcx>) -> bool { match t.sty { - ty::TyProjection(..) if !self.include_nonconstraining => { + ty::TyProjection(..) | ty::TyAnon(..) if !self.include_nonconstraining => { // projections are not injective return false; } diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 01a310da25d..b9e0b4a10ea 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -326,7 +326,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { /* leaf type -- noop */ } - ty::TyClosure(..) => { + ty::TyClosure(..) | ty::TyAnon(..) => { bug!("Unexpected closure type in variance computation"); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 37af778d555..73bc647fa9f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1867,6 +1867,18 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> { ty::TyParam(ref p) => Generic(p.name.to_string()), + ty::TyAnon(def_id, substs) => { + // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, + // by looking up the projections associated with the def_id. + let item_predicates = cx.tcx().lookup_predicates(def_id); + let substs = cx.tcx().lift(&substs).unwrap(); + let bounds = item_predicates.instantiate(cx.tcx(), substs); + let predicates = bounds.predicates.into_vec(); + ImplTrait(predicates.into_iter().filter_map(|predicate| { + predicate.to_opt_poly_trait_ref().clean(cx) + }).collect()) + } + ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton) ty::TyInfer(..) => panic!("TyInfer"), |
